2009-04-22 23 views
31

Estoy buscando un proceso con el nombre de "MyApp.exe" y quiero asegurarme de obtener el proceso que pertenece a un usuario en particular.¿Cómo determino el propietario de un proceso en C#?

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

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

Esto me da una lista de procesos, pero no parece ser una forma en la clase de proceso para determinar quién es el dueño ¿proceso? ¿Alguna idea sobre cómo puedo hacer esto?

Respuesta

53

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

Por identificador 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 (busca el primer proceso sólo, ajustar 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"; 
} 
+0

En el segundo método, el anidado si contiene una cadena, propietario. Creo que tenías la intención de devolver esa cadena, en su lugar. – crftr

+0

Gracias Mike, lo arregló. –

+1

Una palabra de advertencia: las consultas de WMI como estas solo están disponibles con los privilegios adecuados. Las cuentas que no son administradores generalmente no tienen acceso a los proveedores de WMI, incluido Win32_Process. http://msdn.microsoft.com/en-us/library/windows/desktop/aa394603%28v=vs.85%29.aspx – Korey

7

Aquí está la versión VB para las personas que no hablan 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 
+8

La pregunta no solicita VB. Si se siente ansioso, intente hacer una nueva pregunta ("cómo hacer esto en VB") y respóndalo usted mismo: los "hablantes que no son C#" buscarán etiquetas que no sean VB. – Superbest

+4

En realidad, soy un desarrollador de C# que tiene que escribir esto en VB.NET. Busqué C# para poder entenderlo rápidamente. Tener el código VB aquí también me ahorró mucho tiempo. Gracias. –

0

Agregar una referencia a su proyecto:

System.Management 

continuación, agregue el siguiente método para 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; 
    } 

A continuación, agregue este método:

public DataTable GetProcessTable() 
    { 
     DataTable MethodResult = null; 
     try 
     { 
      List<Process> Processes = Process.GetProcesses().ToList<Process>(); 

      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; 
    } 

Calling GetProcessTable() le da un DataTable de todos los procesos que se ejecutan junto con su Id and Name, que es útil porque se puede usar como un parámetro Datasource de DataGridView.

Deseo saber si necesita más campos para agregar a la tabla.

12

Desde WMI no siempre es una forma rápida de recuperación de información, aquí es la relación P/Invoke manera natural de hacerlo:

El valor de retorno es null cuando no es satisfactorio. 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); 
+0

Acepto, gracias por esta alternativa, no es saludable usar WMI fuera de las aplicaciones internas de inventario de negocios (es lento, y en el mundo en general se corrompe/rompe con frecuencia). – BTJ

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

Una explicación sobre esto sería útil. – jHilscher

+0

Lo sentimos, no es la respuesta a la pregunta de este hilo. Simplemente muestra el ID de usuario del proceso (cuenta de Windows) en una aplicación .NET en tiempo de ejecución. –

+0

Esto es útil para tareas relacionadas, como "obtener los procesos del usuario actual", que es cómo llegué aquí – pomeroy

-1

Esta es la manera 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 
} 
+3

Devuelve el nombre de usuario del proceso actual. La propiedad de entorno no puede obtener variables de entorno de otro proceso. – palota

+0

¿Cómo obtener el nombre de usuario de otro proceso? –

Cuestiones relacionadas