【发布时间】:2021-09-18 02:42:43
【问题描述】:
我有以下 .NET 代码可以访问OpenProcessToken Win32 API 以检索系统上所有进程的所有者名称:
using System.Security.Principal;
using System.Runtime.InteropServices;
public class Test
{
[DllImport("advapi32.dll", SetLastError=true)]
[return: MarshalAs(UnmanagedType.Bool)]
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);
private const UInt32 TOKEN_QUERY = 0x0008;
public static List<List<String>> GetProcessWithUsers()
{
var processes = Process.GetProcesses();
var result = new List<List<string>>();
foreach (var proc in processes)
{
result.Add(new List<string> { proc.ProcessName, GetProcessUser(proc) });
}
return result;
}
public static string GetProcessUser(Process process)
{
IntPtr tokenHandle = IntPtr.Zero;
try
{
OpenProcessToken(process.Handle, TOKEN_QUERY, out tokenHandle);
WindowsIdentity wi = new WindowsIdentity(tokenHandle);
return wi.Name;
}
catch
{
return null;
}
finally
{
if (tokenHandle != IntPtr.Zero)
{
CloseHandle(tokenHandle);
}
}
}
}
调用Test.GetProcessWithUsers()(例如在 LinqPad 中)对于我系统上的 280 个进程大约需要 2 秒。
我认为这个任务的时间是可以接受的。
Process.GetProcesses() 很活泼,new WindowsIdentity() 的贡献可以忽略不计,那么OpenProcessToken() 的阻碍是什么?是否有其他更快的 Win32 API 函数?
【问题讨论】:
-
Process.Handle 是问题(导致访问被拒绝)。如果您以管理员身份运行,应该会快得多。如果您追求性能,您可以使用 P/Invoke 编写整个内容来避免这种情况
-
@SimonMourier 我不能以管理员身份运行它,就是这样。
-
我明白,但它更快吗?如果是,则使用完整的 P/Invoke 重写
-
OpenProcessToken没问题,如果您有PROCESS_QUERY_LIMITED_INFORMATION访问权限的进程句柄,则不会造成任何问题或减速。但是 - 收集所有者 sids 的意义/最终目标是什么? -
这是一个应该更快的版本(完整 p/invoke)pastebin.com/raw/ae5Eg9iP