¿Cómo determino el propietario de un proceso en C #?

Estoy buscando un proceso con el nombre de “MyApp.exe” y quiero asegurarme de obtener el proceso que pertenece a un usuario en particular.

Uso el siguiente código para obtener una lista de los procesos:

Process[] processes = Process.GetProcessesByName("MyApp"); 

Esto me da una lista de procesos, pero no parece haber una forma en la clase Process para determinar a quién pertenece ese proceso. ¿Alguna idea sobre cómo puedo hacer esto?

Puede usar WMI para que el usuario sea dueño de un determinado proceso. Para usar WMI, necesita agregar una referencia a System.Management.dll a su proyecto.

Por id de proceso:

 public string GetProcessOwner(int processId) { string query = "Select * From Win32_Process Where ProcessID = " + processId; ManagementObjectSearcher searcher = new ManagementObjectSearcher(query); ManagementObjectCollection processList = searcher.Get(); foreach (ManagementObject obj in processList) { string[] argList = new string[] { string.Empty, string.Empty }; int returnVal = Convert.ToInt32(obj.InvokeMethod("GetOwner", argList)); if (returnVal == 0) { // return DOMAIN\user return argList[1] + "\\" + argList[0]; } } return "NO OWNER"; } 

Por nombre del proceso (encuentra el primer proceso solamente, ajuste en consecuencia):

 public string GetProcessOwner(string processName) { string query = "Select * from Win32_Process Where Name = \"" + processName + "\""; ManagementObjectSearcher searcher = new ManagementObjectSearcher(query); ManagementObjectCollection processList = searcher.Get(); foreach (ManagementObject obj in processList) { string[] argList = new string[] { string.Empty, string.Empty }; int returnVal = Convert.ToInt32(obj.InvokeMethod("GetOwner", argList)); if (returnVal == 0) { // return DOMAIN\user string owner = argList[1] + "\\" + argList[0]; return owner; } } return "NO OWNER"; } 

Como WMI no siempre es una forma rápida de recuperar información, aquí está la forma nativa de P / Invoke de hacerlo:

El valor de retorno es null cuando no tiene éxito. Para obtener los nombres de los procesos que se ejecutan bajo el usuario del SISTEMA, debe ejecutar este código como administrador.

 private static string GetProcessUser(Process process) { IntPtr processHandle = IntPtr.Zero; try { OpenProcessToken(process.Handle, 8, out processHandle); WindowsIdentity wi = new WindowsIdentity(processHandle); string user = wi.Name; return user.Contains(@"\") ? user.Substring(user.IndexOf(@"\") + 1) : user; } catch { return null; } finally { if (processHandle != IntPtr.Zero) { CloseHandle(processHandle); } } } [DllImport("advapi32.dll", SetLastError = true)] private static extern bool OpenProcessToken(IntPtr ProcessHandle, uint DesiredAccess, out IntPtr TokenHandle); [DllImport("kernel32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool CloseHandle(IntPtr hObject); 

Aquí está la versión de VB para los altavoces que no C #:

 Function GetProcessOwner(ProcessName As String) As String Dim query = "Select * from Win32_Process Where Name = """ + ProcessName + """" Dim searcher = New ManagementObjectSearcher(query) Dim processList = searcher.Get() For Each obj As ManagementObject In processList Dim argList As String() = {String.Empty, String.Empty} Dim returnVal = Convert.ToInt32(obj.InvokeMethod("GetOwner", argList)) If returnVal = 0 Then ' return DOMAIN\user Dim owner = argList(1) + "\\" + argList(0) Return owner End If Next Return "NO OWNER" End Function Function GetProcessOwner(processId As Integer) As String Dim query = "Select * From Win32_Process Where ProcessID = " & processId Dim searcher = New ManagementObjectSearcher(query) Dim processList = searcher.Get() For Each obj As ManagementObject In processList Dim argList As String() = {String.Empty, String.Empty} Dim returnVal = Convert.ToInt32(obj.InvokeMethod("GetOwner", argList)) If returnVal = 0 Then ' return DOMAIN\user Return argList(1) + "\\" + argList(0) End If Next Return "NO OWNER" End Function 

Lamentablemente, no existe una forma .Net nativa de obtener el propietario del proceso.

Echa un vistazo a estos para encontrar una solución potencial:

 System.Security.Principal.WindowsIdentity.GetCurrent().Name 

Agregue una referencia a su proyecto:

 System.Management 

A continuación, agregue el siguiente método a su proyecto:

  public string GetProcessOwner(int processId) { string MethodResult = null; try { StringBuilder sb = new StringBuilder(); sb.Append(" SELECT "); sb.Append(" * "); sb.Append(" FROM "); sb.Append(" WIN32_PROCESS"); sb.Append(" WHERE "); sb.Append(" ProcessId = " + processId); string Query = sb.ToString(); ManagementObjectCollection Processes = new ManagementObjectSearcher(Query).Get(); foreach (ManagementObject Process in Processes) { string[] Args = new string[] { "", "" }; int ReturnCode = Convert.ToInt32(Process.InvokeMethod("GetOwner", Args)); switch(ReturnCode) { case 0: MethodResult = Args[1] + "\\" + Args[0]; break; default: MethodResult = "None"; break; } } } catch //(Exception ex) { //ex.HandleException(); } return MethodResult; } 

Luego agrega este método:

  public DataTable GetProcessTable() { DataTable MethodResult = null; try { List Processes = Process.GetProcesses().ToList(); DataTable dt = new DataTable(); dt.Columns.Add("Name", typeof(string)); dt.Columns["Name"].ReadOnly = true; dt.Columns.Add("Id", typeof(string)); dt.Columns["Id"].ReadOnly = true; dt.Columns.Add("Owner", typeof(string)); dt.Columns["Owner"].ReadOnly = true; foreach (Process p in Processes) { DataRow r = dt.NewRow(); bool Match = false; r["Id"] = p.Id.ToString(); r["Name"] = p.ProcessName; r["Owner"] = GetProcessOwner(p.Id); dt.Rows.Add(r); } MethodResult = dt; } catch //(Exception ex) { //ex.HandleException(); } return MethodResult; } 

Llamar a GetProcessTable () le proporciona una DataTable de todos los procesos en ejecución junto con su Id y Name, que es útil porque puede usarse como un parámetro Datasource de DataGridView.

Avíseme si necesita agregar más campos a la tabla.

Esta es la forma más fácil que he encontrado para hacerlo:

 Process[] processes = Process.GetProcessesByName("MyApp"); foreach (Process process in processes) { string username = process.StartInfo.Environment["USERNAME"]; // do some stuff }