【问题标题】:Process Id's and process names进程 ID 和进程名称
【发布时间】:2011-05-02 13:48:48
【问题描述】:

我正在创建一个基本上扫描系统以查看特定进程是否正在运行的 Windows 程序。我只有进程名称 (AcroRd32.exe),没有别的。

根据我所读到的最简单的方法,使用 CreateToolhelp32Snapshot 创建所有进程的快照,然后遍历每个进程以查找进程名称。

我的应用程序以高性能为中心。那么有没有更好更有效的方法来做到这一点。 该应用程序每隔几秒钟收集一次快照。迭代快照中的 100 个进程似乎效率不高。是否有直接的 API 可以通过进程名称找到进程(并通过名称检索进程句柄或 id)?

我进行了广泛的搜索,但运气不佳。以前有人试过吗?

【问题讨论】:

  • 如果有多个进程同名怎么办?
  • 我计划跟踪进程 ID 以区分具有相同名称的不同进程
  • 是的,那么您可能必须自己遍历所有进程并找出具有相同名称的句柄。
  • 快照实际上是一个列表还是你可以二进制搜索它?

标签: c++ c windows winapi


【解决方案1】:

扫描进程的最快方法是通过 NTDLL 的 NtQuerySystemInformation 调用。它通过一次调用(或在极少数情况下,即大量进程)为您提供系统上所有进程的名称和进程 ID 列表。您可以结合 NtQuerySystemInformation 并使用哈希来进行字符串比较,而不是比较每个字节。

// headers @ http://pastebin.com/HWzJYpbv


NtQuerySystemInformation = (_RT_NAPI_QUERYSYSINFO)GetProcAddress(GetModuleHandleA("NTDLL.DLL"), "NtQuerySystemInformation");

    // Get process information buffer
    do {
        // Allocate buffer for process info
        pBuffer = HeapAlloc(hHeap, HEAP_ZERO_MEMORY, cbBuffer); 
        if (pBuffer == NULL) {
            // Cannot allocate enough memory for buffer (CRITICAL ERROR)
            return 1;
        }

        // Obtain system process snapshot
        Status = NtQuerySystemInformation(5, pBuffer, cbBuffer, NULL);

        // Allocate bigger buffer for moar data
        if (Status == STATUS_INFO_LENGTH_MISMATCH) {
            HeapFree(hHeap, 0, pBuffer);
            cbBuffer *= 2; // Increase the size of the buffer :-)
        } else if ((Status) != 0x00) {
            // Can't query process information (probably rootkit or anti-virus)
            HeapFree(hHeap, 0, pBuffer);
            return 1;
        }
    } while (Status == STATUS_INFO_LENGTH_MISMATCH);

    // Get pointer to first system process info structure
    pInfo = (PSYSTEM_PROCESS_INFORMATION)pBuffer;

    // Loop over each process
    for (;;) {
        // Get process name
        pszProcessName = pInfo->ImageName.Buffer;

        // ... do work. For a fast string compare, calculate a 32-bit hash of the string, then compare to a static hash.
        if(CRC32(pszProcessName) == 0xDEADBEEF /* <- hash of adobe reader process name goez here */) {
            // Found process
        }

        // Load next entry
        if (pInfo->NextEntryOffset == 0)
            break;
        pInfo = (PSYSTEM_PROCESS_INFORMATION)(((PUCHAR)pInfo)+ pInfo->NextEntryOffset);
    }

在 Windows 2000 - Windows 7 英文版 x64/x86(Win XP x64 除外)上测试 注意:它将所有进程返回到 64 位系统上的 32 位 WOW64 进程。

【讨论】:

    【解决方案2】:

    没有。

    每个进程都有一个唯一的 ID,但不是唯一的名称。可能有多个同名的进程。因此,如果不遍历所有进程,就不可能直接从名称中获取进程句柄。

    在内部,所有进程都以某种方式链接在一起,例如,在链表中。即使提供了一个函数GetProcessByName(),它也会在内部遍历列表以代表您查找具有该名称的那些进程。所以这不会对性能产生很大影响。

    一边

    试一试EnumProcesses(),它的开销更少且更简单。检查here

    BOOL WINAPI EnumProcesses(
      __out  DWORD *pProcessIds,
      __in   DWORD cb,
      __out  DWORD *pBytesReturned
    );
    

    MSDN 对此有一个 example

    【讨论】:

    • 其实Windows上会有多个名为'svchost.exe'的进程;它们因运行的用户而异。
    • 是的,我以前遇到过很多关于 Windows 的示例。
    • 谢谢,我想我得到了我想要的东西
    猜你喜欢
    • 2011-05-05
    • 1970-01-01
    • 2015-01-28
    • 2012-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多