本文示範如何在 VC++ 中使用 Toolhelp32 序列函數 列舉系統進程、取得各進程載入的模組 (DLL/EXE) 資訊、記憶體使用狀況,並解決權限不足導致的 OpenProcess 失敗問題。
CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0) 建立進程快照;Process32First / Process32Next 遍歷 PROCESSENTRY32;OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);GetProcessMemoryInfo 取得記憶體計數器;GetProcessModule 列舉模組(內部再建立 TH32CS_SNAPMODULE 快照)。BOOL CMyDlg::GetProcessModule(DWORD dwPID, DWORD dwModuleID,
LPMODULEENTRY32 lpMe32, DWORD cbMe32)
{
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPID);
if (hSnap == INVALID_HANDLE_VALUE) return FALSE;
MODULEENTRY32 me32 = { sizeof(MODULEENTRY32) };
BOOL bFound = FALSE;
if (Module32First(hSnap, &me32)) {
do {
if (me32.th32ModuleID == dwModuleID) {
CopyMemory(lpMe32, &me32, cbMe32);
bFound = TRUE;
break;
}
} while (Module32Next(hSnap, &me32));
}
CloseHandle(hSnap);
return bFound;
}
若 OpenProcess 返回 ERROR_ACCESS_DENIED (5),需調整當前進程 Token:
BOOL EnableDebugPrivilege()
{
HANDLE hToken;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
return FALSE;
TOKEN_PRIVILEGES tp = { 1 };
LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid);
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
BOOL ok = AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL);
CloseHandle(hToken);
return ok && GetLastError() == ERROR_SUCCESS;
}
在列舉進程前呼叫 EnableDebugPrivilege() 即可存取系統進程 (如 csrss.exe)。
作者提到:如何取得進程中各執行緒所屬的模組名稱? Toolhelp32 僅能列舉進程層級模組,執行緒層級模組需結合 Thread32First + 模組快照進一步關聯,歡迎高手補充。