在 Windows 9x 系列中,可使用 ToolHelp API(CreateToolhelp32Snapshot、Process32First/Next)輕鬆取得處理序名稱與路徑。但這套 API 在 NT 核心系統(NT 4.0、2000、XP 及後續版本)中表現不同:PROCESSENTRY32 結構的 szExeFile 僅回傳檔案名稱,不含完整路徑。
NT 系統提供 PSAPI,透過三個關鍵函式即可取得完整路徑:
OpenProcess:以 PROCESS_QUERY_INFORMATION | PROCESS_VM_READ 權限開啟目標處理序。EnumProcessModules:列舉該處理序載入的模組,取得主模組句柄。GetModuleFileNameEx:依模組句柄取得完整路徑。//////////////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <windows.h>
#include "PSAPI.H"
#pragma comment(lib, "PSAPI.LIB")
int main(void)
{
DWORD processId[1024], needed, processCount, i;
HANDLE hProcess;
HMODULE hModule;
char path[MAX_PATH] = "", temp[256];
printf("ShowProcessPath with [Process Status API]\n\n");
EnumProcesses(processId, sizeof(processId), &needed);
processCount = needed / sizeof(DWORD);
for (i = 0; i < processCount; i++)
{
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processId[i]);
if (hProcess)
{
EnumProcessModules(hProcess, &hModule, sizeof(hModule), &needed);
GetModuleFileNameEx(hProcess, hModule, path, sizeof(path));
GetShortPathName(path, path, 256);
itoa(processId[i], temp, 10);
printf("%s --- %s\n", path, temp);
CloseHandle(hProcess);
}
else
{
printf("Failed!!!\n");
}
}
CloseHandle(hModule);
itoa(processCount, temp, 10);
printf("\nProcess Count: %s\n\n", temp);
return 0;
}
| 處理序名稱 | PSAPI | ToolHelp API |
|---|---|---|
| smss.exe | Y | N |
| csrss.exe | N | N |
| winlogon.exe | Y | N |
| services.exe | Y | N |
| lsass.exe | Y | N |
| svchost.exe | Y | N |
| WinMgmt.exe | Y | N |
| Explorer.EXE | Y | Y |
| mobsync.exe | Y | Y |
| conime.exe | Y | Y |
註:Y = 成功取得路徑,N = 失敗。PSAPI 對大多數系統程序皆可取得路徑,唯 csrss.exe 仍受保護無法存取(需參考補充版文章提升 SE_DEBUG_NAME 權限)。
本文配套原始碼可供下載。