開發任務管理器、安全防護軟件或系統優化工具時,常需:
Windows 提供 tlhelp32.h API,通過快照機制獲取進程靜態視圖:
HANDLE CreateToolhelp32Snapshot(DWORD dwFlags, DWORD th32ProcessID);
BOOL Process32First(HANDLE hSnapshot, LPPROCESSENTRY32 lppe);
BOOL Process32Next(HANDLE hSnapshot, LPPROCESSENTRY32 lppe);
PROCESSENTRY32 關鍵字段:
| 字段 | 含義 |
|---|---|
| th32ProcessID | 進程 PID |
| th32ParentProcessID | 父進程 PID(構建進程樹關鍵) |
| szExeFile | 可執行文件名(MAX_PATH) |
| cntThreads | 線程數 |
| pcPriClassBase | 優先級基值 |
#include
#include
void EnumerateProcesses(TListView* listView) {
listView->Items->Clear();
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnapshot == INVALID_HANDLE_VALUE) return;
PROCESSENTRY32 pe32 = { sizeof(PROCESSENTRY32) };
if (!Process32First(hSnapshot, &pe32)) {
CloseHandle(hSnapshot);
return;
}
do {
TListItem* item = listView->Items->Add();
item->Caption = pe32.szExeFile;
item->SubItems->Add(IntToStr(pe32.th32ParentProcessID));
item->SubItems->Add(IntToHex(pe32.th32ProcessID, 8).UpperCase());
// 獲取文件版本信息
String exePath = GetFullPath(pe32.szExeFile); // 需實現路徑搜索邏輯
if (FileExists(exePath)) {
DWORD handle, size = GetFileVersionInfoSize(exePath.c_str(), &handle);
if (size > 0) {
std::vector buffer(size);
if (GetFileVersionInfo(exePath.c_str(), 0, size, buffer.data())) {
UINT len;
LPVOID ptr;
// 文件版本
if (VerQueryValue(buffer.data(), L"\\StringFileInfo\\040904E4\\FileVersion", &ptr, &len))
item->SubItems->Add((wchar_t*)ptr);
// 公司名
if (VerQueryValue(buffer.data(), L"\\StringFileInfo\\040904E4\\CompanyName", &ptr, &len))
item->SubItems->Add((wchar_t*)ptr);
// 文件描述
if (VerQueryValue(buffer.data(), L"\\StringFileInfo\\040904E4\\FileDescription", &ptr, &len))
item->SubItems->Add((wchar_t*)ptr);
}
}
}
} while (Process32Next(hSnapshot, &pe32));
CloseHandle(hSnapshot);
}
直接終止子進程可能導致殭屍進程或資源洩漏。正確做法:
th32ParentProcessID)OpenProcess(PROCESS_TERMINATE, FALSE, parentPID)TerminateProcess(hProcess, EXIT_CODE)bool TerminateProcessTree(DWORD targetPID) {
// 1. 獲取父進程 PID(實際場景中可能需遞歸查找頂層父進程)
DWORD parentPID = GetParentPID(targetPID); // 從快照中查找
// 2. 打開父進程
HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, parentPID);
if (!hProcess) return false;
// 3. 終止
BOOL result = TerminateProcess(hProcess, 0xDEAD);
CloseHandle(hProcess);
return result;
}
終止前必須檢查白名單,防止誤殺導致系統崩潰:
const wchar_t* CRITICAL_PROCESSES[] = {
L"csrss.exe", L"wininit.exe", L"services.exe", L"lsass.exe",
L"smss.exe", L"winlogon.exe", L"svchost.exe", L"explorer.exe",
L"System", L"Registry", L"fontdrvhost.exe", L"dwm.exe"
};
bool IsCriticalProcess(const wchar_t* exeName) {
for (auto critical : CRITICAL_PROCESSES) {
if (_wcsicmp(exeName, critical) == 0) return true;
}
return false;
}
using System.Diagnostics;
using System.Linq;
public class ProcessManager {
public ProcessInfo[] GetAllProcesses() {
return Process.GetProcesses()
.Where(p => !IsCriticalProcess(p.ProcessName))
.Select(p => new ProcessInfo {
Id = p.Id,
Name = p.ProcessName,
MainModulePath = GetModulePathSafe(p),
ParentId = GetParentProcessId(p.Id),
FileVersion = GetFileVersion(p),
Company = GetCompanyName(p),
Description = GetDescription(p)
}).ToArray();
}
public bool KillProcessTree(int pid) {
var parent = Process.GetProcessById(pid);
if (IsCriticalProcess(parent.ProcessName)) return false;
try {
parent.Kill(); // 會遞歸終止子進程
parent.WaitForExit(5000);
return true;
} catch {
return false;
}
}
private string GetModulePathSafe(Process p) {
try { return p.MainModule.FileName; } catch { return "Access Denied"; }
}
}
requireAdministrator,或使用 OpenProcessToken + AdjustTokenPrivileges 啟用 SE_DEBUG_PRIVILEGEexplorer.exe 或 services.exe),需實時刷新快照ObservableCollection 或 VirtualizingStackPanel掌握進程枚舉與終止的核心邏輯,是構建系統級工具、EDR Agent、自動化測試框架的基石。