最快的,在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;
    }

最快的,在c#中获取运行进程列表及其Id和位置的CPU消耗最少的方法

最后我决定走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;
    }