2009-04-22 3 views
31

Я ищу процесс под названием «MyApp.exe», и я хочу убедиться, что я получаю процесс, принадлежащий определенному пользователю.Как определить владельца процесса на C#?

Я использую следующий код, чтобы получить список процессов:

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

Это дает мне список процессов, но не кажется, путь в классе процессов, чтобы определить, кто владеет тем обработать? Любые мысли о том, как я могу это сделать?

ответ

53

Вы можете использовать WMI, чтобы получить пользователя, владеющего определенным процессом. Чтобы использовать WMI, вам необходимо добавить ссылку на проект System.Management.dll.

По идентификатору процесса:

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

По имени процесса (находит только первый процесс, скорректировать соответствующий образ):

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

В вашем втором методе, ваш вложенный, если содержит строку, владелец. Я верю, что вы намеревались вернуть эту строку. – crftr

+0

Спасибо, Майк, исправил это. –

+1

Слово предупреждения: запросы WMI, подобные этим, доступны только с соответствующими привилегиями. Обычно учетные записи, отличные от администратора, не имеют доступа к поставщикам WMI, включая Win32_Process. http://msdn.microsoft.com/en-us/library/windows/desktop/aa394603%28v=vs.85%29.aspx – Korey

7

Вот версия VB для не 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

Вопрос не требует VB. Если вы испытываете желание, попробуйте задать новый вопрос («как это сделать в VB») и ответьте сами: «Non C# speakers» будет искать теги, отличные от VB. – Superbest

+4

На самом деле, я разработчик C#, который должен написать это в VB.NET. Я искал C#, чтобы я мог быстро это понять. Наличие здесь кода VB также помогло мне много времени. Спасибо. –

0

Добавить ссылка на ваш проект:

System.Management 

Затем добавьте следующий метод к вашему проекту:

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

Затем добавьте этот метод:

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

Вызов GetProcessTable() дает вам DataTable всех запущенных процессов наряду с их Id и Name, что удобно, поскольку оно может использоваться в качестве параметра Datasource DataGridView.

Дайте мне знать, если вам нужно больше полей, добавляющих в таблицу.

12

Поскольку WMI не всегда быстрый способ получения информации, здесь является родным P/Invoke способ сделать это:

Возвращаемое значение null в случае неудачи. Чтобы получить имена процессов, запущенных под пользователем SYSTEM, вам необходимо выполнить этот код как администратор.

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

Согласен, спасибо за эту альтернативу, нездорово использовать WMI за пределами приложений для внутреннего бизнеса (он медленный, а в мире в целом часто поврежден/нарушен). – BTJ

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

Объяснение этому было бы полезно. – jHilscher

+0

Извините, это не ответ на вопрос этой темы. Он просто показывает идентификатор пользователя процесса (учетную запись Windows) в приложении .net во время выполнения. –

+0

Это полезно для связанных задач, таких как «получить текущие пользовательские процессы», вот как я приземлился здесь – pomeroy

-1

Это самый простой способ я нашел, чтобы сделать это:

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

    // do some stuff 
} 
+3

Он возвращает имя пользователя текущего процесса. Свойство Environment не может получить переменные среды из другого процесса. – palota

+0

Как получить имя пользователя другого процесса? –

Смежные вопросы