MFC 中點擊按鈕終止進程(如 explorer.exe),雖可直接調用 TerminateProcess,但這是「暴力殺進程」,會導致目標進程無釋放資源、保存數據。本文詳解正規姿勢與工程化替代方案。
#include
// 獲取進程 PID
DWORD GetProcessIdByName(LPCTSTR szProcessName) {
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32 pe32 = { sizeof(PROCESSENTRY32) };
DWORD pid = 0;
if (Process32First(hSnap, &pe32)) {
do {
if (_tcsicmp(pe32.szExeFile, szProcessName) == 0) {
pid = pe32.th32ProcessID;
break;
}
} while (Process32Next(hSnap, &pe32));
}
CloseHandle(hSnap);
return pid;
}
// 終止進程
void KillProcess(LPCTSTR szProcessName) {
DWORD pid = GetProcessIdByName(szProcessName);
if (pid == 0) return; // 未找到
HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, pid);
if (hProcess) {
TerminateProcess(hProcess, 0); // 暴力終止
CloseHandle(hProcess);
}
}
// 按鈕點擊處理
void CMyDlg::OnBnClickedBtnKillExplorer() {
KillProcess(_T("explorer.exe"));
}
PROCESS_TERMINATE 權限,終止系統進程需管理員權限(清單 requireAdministrator)TerminateProcess 不執行 DLL DLL_PROCESS_DETACH、不刷新文件緩衝、不釋放鎖,極易損壞數據Ctrl+Shift+Esc 重啟
// 針對有主窗口的 GUI 程序
HWND hWnd = FindWindow(_T("Shell_TrayWnd"), NULL); // Explorer 任務欄類名
if (hWnd) PostMessage(hWnd, WM_CLOSE, 0, 0);
優點:目標進程可執行清理邏輯。缺點:僅適用於有消息循環的 GUI 進程。
WM_QUERYENDSESSION / WM_ENDSESSION(系統關機協議)
// 模擬系統關機通知,所有頂層窗口收到可攔截
SendMessageTimeout(HWND_BROADCAST, WM_QUERYENDSESSION, 0, ENDSESSION_CLOSEAPP,
SMTO_ABORTIFHUNG, 5000, NULL);
ntsd -c q -pn:process.exe(調試器分離法)
// 簡單粗暴但比 TerminateProcess 稍優(會觸發調試器分離流程)
WinExec(_T("ntsd -c q -pn:explorer.exe"), SW_HIDE);
原理:ntsd (Windows 內建調試器) 附加進程後執行 q (quit) 命令分離,進程正常退出。
SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
SC_HANDLE hSvc = OpenService(hSCM, _T("ServiceName"), SERVICE_STOP);
SERVICE_STATUS ss;
ControlService(hSvc, SERVICE_CONTROL_STOP, &ss);
WM_CUSTOM_EXIT 或命名管道/IPC 命令PostMessage(WM_CLOSE) 或 ntsd -c q -pnControlService 或 OpenProcess+TerminateProcess (最後手段)切記:TerminateProcess 是「核按鈕」,僅在無其他選擇且接受數據丟失風險時使用。