關鍵業務程式必須長期穩定運行,但死鎖、無響應等問題難以完全避免。當修復 Bug 時間緊迫且問題難以重現時,「軟體看門狗」可作為臨時保護機制。其核心需求包括:隱藏運行介面、定時檢測目標進程存活、判斷程式無響應並強制終止、超過閾值自動重啟系統。
Windows 提供兩個未文檔化函數(位於 User32.dll):
IsHungAppWindow(HWND) - 以視窗句柄為參數IsHungThread(DWORD threadId) - 以執行緒 ID 為參數需動態載入:
if (m_hUser32 == NULL)
m_hUser32 = GetModuleHandle("USER32.DLL");
if (m_hUser32) {
m_IsHungNT = (HUNG_FUNNT)GetProcAddress(m_hUser32, "IsHungAppWindow");
m_IsHung9X = (HUNG_FUN9X)GetProcAddress(m_hUser32, "IsHungThread");
}
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) {
if (!CFrameWnd::PreCreateWindow(cs)) return FALSE;
cs.dwExStyle |= WS_EX_TOOLWINDOW; // 不在任務列顯示
cs.style = WS_POPUP; // 隱藏主視窗
return TRUE;
}
bool CWatchDogApp::IsUniqueCopyInProc() {
m_Mutex = CreateMutex(NULL, TRUE, "System Watch Dog");
return GetLastError() != ERROR_ALREADY_EXISTS;
}
// InitInstance 中調用
if (!IsUniqueCopyInProc()) return FALSE;
bool CWatchDogApp::IsWinNT() {
OSVERSIONINFO osvi = { sizeof(OSVERSIONINFO) };
GetVersionEx(&osvi);
return osvi.dwPlatformId == VER_PLATFORM_WIN32_NT;
}
if (IsWinNT()) {
HANDLE hToken; TOKEN_PRIVILEGES tp; LUID luid;
OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);
LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &luid);
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL);
return ExitWindowsEx(EWX_REBOOT | EWX_FORCE, 0);
}
return ExitWindowsEx(EWX_REBOOT | EWX_FORCE, 0);
// 啟動進程
CreateProcess(path, NULL, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi);
// 終止進程(謹慎使用,不會觸發 DLL 卸載通知)
TerminateProcess(hProcess, 0);
修改註冊表 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon:
AutoAdminLogon = "1"、DefaultUserName、DefaultPassword 實現自動登入Shell 值從 explorer.exe 改為自訂程式絕對路徑,實現登入後直接啟動啟動 WatchDog 後,會自動啟動模擬無響應的 HungDemo 程式。WatchDog 檢測到無響應即終止並重啟,重複 6 次後觸發系統自動重啟。測試前請保存工作資料。