代码之家  ›  专栏  ›  技术社区  ›  adeel825

如何在c_中确定流程的所有者?

  •  38
  • adeel825  · 技术社区  · 15 年前

    我正在寻找一个名为“myapp.exe”的进程,我想确保我得到了由特定用户拥有的进程。

    我使用以下代码获取进程列表:

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

    这给了我一个进程列表,但是在process类中似乎没有方法确定谁拥有该进程?你有什么想法吗?

    7 回复  |  直到 8 年前
        1
  •  58
  •   Dirk Vollmar    8 年前

    您可以使用wmi获取拥有某个进程的用户。要使用wmi,需要添加对 System.Management.dll 你的项目。

    按进程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";
    }
    

    按进程名称 (仅查找第一个进程,相应地进行调整):

    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";
    }
    
        2
  •  20
  •   bytecode77    8 年前

    由于wmi并不总是一种快速检索信息的方法,下面是进行此操作的本机p/invoke方法:

    返回值为 null 不成功时。为了获取在系统用户下运行的进程的名称,您需要以管理员身份执行此代码。

    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);
    
        3
  •  7
  •   Stefano    12 年前

    以下是非C扬声器的VB版本:

    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
    
        4
  •  4
  •   Damovisa    15 年前

    不幸的是,没有本机的.NET方法来获取进程所有者。

    请查看这些潜在解决方案:

        5
  •  0
  •   WonderWorker Sakal    8 年前

    添加对项目的引用:

    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()将为您提供一个包含所有正在运行的进程及其ID和名称的数据表,这很方便,因为它可以用作DataGridView的数据源参数。

    如果需要在表中添加更多字段,请通知我。

        6
  •  0
  •   Laurel keremk    8 年前
    System.Security.Principal.WindowsIdentity.GetCurrent().Name
    
        7
  •  -1
  •   Fallon Yager    8 年前

    这是我发现的最简单的方法:

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