我正在创建一个基本扫描系统的Windows程序,以查看特定进程是否正在运行。我有进程名称(AcroRd32.exe),没有别的。
从我读过的最简单的方法是使用 CreateToolhelp32Snapshot 创建所有进程的快照,然后遍历每个进程以查找进程名称。
我的应用程序非常以性能为中心。那么有更好的更有效的方法来做到这一点。 应用程序每隔几秒收集一次快照。迭代快照中的100个进程似乎效率不高。是否有直接API可以通过其进程名称找到进程(并通过名称检索进程句柄或id)?
我没有太多运气就广泛搜索过。有人曾尝试过这个吗?
答案 0 :(得分:4)
扫描进程的最快方法是通过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进程。
答案 1 :(得分:3)
否强>
每个流程都有唯一ID ,但不是唯一名称。可能有多个具有相同名称的进程。因此,如果不迭代所有进程,就不可能直接从其名称中获取进程句柄。
在内部所有的行为以某种方式链接在一起,例如,在链表中。即使提供了一个函数GetProcessByName()
,它也会在内部遍历列表,以便代表您查找具有该名称的进程。所以这不会对性能产生很大的影响。
<强>除了强>
向EnumProcesses()
投射,其开销较小且更简单。检查here。
BOOL WINAPI EnumProcesses(
__out DWORD *pProcessIds,
__in DWORD cb,
__out DWORD *pBytesReturned
);
MSDN对此有一个example。