最快的,在c#中获取运行进程列表及其Id和位置的CPU消耗最少的方法
本文关键字:位置 Id CPU 方法 列表 进程 运行 获取 | 更新日期: 2023-09-27 17:52:57
我编写了一个模块,用于Windows XP及以上版本每250毫秒获取运行进程列表。我试过。net &;WMI的方式,它们都是非常密集的CPU。在我的机器上,它们都在80ms内完成。在任何一种情况下,我的主机进程CPU都保持在10%到14%以上。我认为Location/ExecutionPath属性才是真正的罪魁祸首。有更好的方法来获取这些信息吗?
Edit1:在我的测试中. net的方式是更密集的CPU,但略快于WMI的方式。WMI方式更慢,但CPU占用更少,因为它将CPU使用转移到WMI提供程序主机
private static int WMIWay()
{
string wmiQueryString = "SELECT ProcessId, ExecutablePath FROM Win32_Process";
using (var searcher = new ManagementObjectSearcher(wmiQueryString))
{
using (var results = searcher.Get())
{
foreach (ManagementObject oReturn in results)
{
if (oReturn["ExecutablePath"] != null)
{
_Processes.Add(new ProcessInfo()
{
ProcessID = (uint)oReturn["ProcessId"],
FilePath = oReturn["ExecutablePath"].ToString(),
});
}
}
return results.Count;
}
}
}
private static int NetWay()
{
var processes = System.Diagnostics.Process.GetProcesses();
foreach (System.Diagnostics.Process runningProcess in processes)
{
if (runningProcess.Id > 4)
{
try
{
_Processes.Add(new ProcessInfo()
{
ProcessID = (uint)runningProcess.Id,
FilePath = runningProcess.MainModule.FileName,
});
}
catch { }
}
}
return processes.Length;
}
最后我决定走PInvoke路线。在我的测试中,这被证明是最好的解决方案。它确实将CPU使用率降低到2%,而且速度也比。net或WMI快。
private static int PInvokeWay()
{
uint[] processIds = new uint[1024];
uint bytesCopied;
uint processCount = 0;
if (ProcessApi.EnumProcesses(processIds, (uint)processIds.Length * sizeof(uint), out bytesCopied) || bytesCopied == 0)
{
processCount = bytesCopied / sizeof(int);
for (int i = 0; i < processCount; i++)
{
string path;
if (Environment.OSVersion.Version.Major >= 6)
path = GetExecutablePathAboveVista(processIds[i]);
else
path = GetExecutablePathXP2003(processIds[i]);
if (!string.IsNullOrWhiteSpace(path))
{
_Processes.Add(new ProcessInfo()
{
ProcessID = processIds[i],
FilePath = path,
});
}
}
}
return (int)processCount;
}
private static string GetExecutablePathAboveVista(uint ProcessId)
{
var buffer = new StringBuilder(1024);
try
{
IntPtr hprocess = ProcessApi.OpenProcess(ProcessApi.PROCESS_QUERY_LIMITED_INFORMATION,
false, ProcessId);
if (hprocess != IntPtr.Zero)
{
try
{
int size = buffer.Capacity;
if (ProcessApi.QueryFullProcessImageName(hprocess, 0, buffer, out size))
{
return buffer.ToString();
}
}
finally
{
ProcessApi.CloseHandle(hprocess);
}
}
}
catch { }
return string.Empty;
}
private static string GetExecutablePathXP2003(uint processId)
{
var buffer = new StringBuilder(1024);
try
{
IntPtr process = ProcessApi.OpenProcess(ProcessApi.PROCESS_QUERY_INFORMATION
| ProcessApi.PROCESS_VM_READ, false, processId);
if (process != IntPtr.Zero)
{
try
{
if (ProcessApi.GetModuleFileNameExW(process, IntPtr.Zero, buffer, buffer.Capacity) != 0)
{
return buffer.ToString();
}
}
finally
{
ProcessApi.CloseHandle(process);
}
}
}
catch { }
return string.Empty;
}