[聚合问答] How do I determine the owner of a process in C#?

c#,.net,process 2018-01-23 35 阅读

I am looking for a process by the name of "MyApp.exe" and I want to make sure I get the process that is owned by a particular user.

I use the following code to get a list of the processes:

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

This gives me a list of processes, but there does not appear to be a way in the Process class to determine who owns that process? Any thoughts on how I can do this?

4个回答

52

You can use WMI to get the user owning a certain process. To use WMI you need to add a reference to the System.Management.dll to your project.

By process id:

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

By process name (finds the first process only, adjust accordingly):

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

2018-01-23
12

Since WMI is not always a fast way of retrieving information, here is the native P/Invoke way of doing it:

The return value is null when unsuccessful. In order to get the names of processes running under the SYSTEM user, you need to execute this code as administrator.

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

2018-01-23
7

Here is the VB version for the non C# speakers:

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

2018-01-23
4

Unfortunately there's no native .Net way of getting the process owner.

Have a look at these for a potential solution:

2018-01-23

注:本文内容来自互联网,旨在为开发者提供分享、交流的平台。如有涉及文章版本等事宜,请你联系站长进行处理。