首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> VC 教學

偵測應用程式是否停止回應:SendMessageTimeout 與未公開 API

     編輯:VC 教學

工作管理員如何判斷某程式「未回應」?核心邏輯是向目標視窗發送訊息並設定超時:若視窗程序在指定時間內未處理,即視為掛住。本文介紹標準做法與兩個未公開的高效替代方案。

標準做法:SendMessageTimeout + WM_NULL

DWORD dwResult;
BOOL bResponsive = SendMessageTimeout(
    hWnd,           // 目標視窗
    WM_NULL,        // 空訊息,不觸發任何動作
    0, 0,           // wParam, lParam
    SMTO_ABORTIFHUNG | SMTO_BLOCK, // 旗標:遇掛住即中止、同步等待
    5000,           // 超時 5 秒
    &dwResult       // 接收回傳值
);

if (!bResponsive) {
    // 視窗未在 5 秒內處理 WM_NULL -> 停止回應
}
  • WM_NULL (0x0000) 是最輕量的測試訊息,任何正常視窗程序都會立即返回 0。
  • SMTO_ABORTIFHUNG 關鍵:若目標佇列已掛住,系統不等待直接返回 FALSE。
  • 此法僅適用於 **GUI 執行緒**(擁有訊息佇列的視窗)。

未公開 API:更直接的判斷

Windows 內部提供兩個未匯出函數,位於 USER32.DLL,需用 GetProcAddress 取得:

1. IsHungAppWindow (NT 系列)

BOOL (WINAPI *IsHungAppWindow)(HWND hWnd);
// 直接判斷視窗所屬執行緒是否掛住

2. IsHungThread (Win9x)

BOOL (WINAPI *IsHungThread)(DWORD dwThreadId);
// 判斷指定執行緒是否掛住

使用範例

HMODULE hUser32 = GetModuleHandle("user32.dll");
auto pIsHungAppWindow = (BOOL(WINAPI*)(HWND))GetProcAddress(hUser32, "IsHungAppWindow");
auto pIsHungThread    = (BOOL(WINAPI*)(DWORD))GetProcAddress(hUser32, "IsHungThread");

bool IsAppHung(HWND hWnd) {
    if (pIsHungAppWindow) return pIsHungAppWindow(hWnd); // NT
    // Win9x 需先取得視窗執行緒 ID
    DWORD dwThreadId = GetWindowThreadProcessId(hWnd, NULL);
    if (pIsHungThread) return pIsHungThread(dwThreadId);
    // 回退標準法
    return !SendMessageTimeout(hWnd, WM_NULL, 0, 0, SMTO_ABORTIFHUNG, 5000, NULL);
}

注意事項

  • 未公開 API 可能在未來版本移除或改變簽名,生產環境建議以標準法為主,未公開法為輔。
  • 主控台程式、服務程式無視窗佇列,此法不適用。
  • 掛住偵測本質是「訊息佇列未處理」,不代表程式邏輯死循環(若邏輯在背景執行緒跑死,GUI 執行緒仍可能回應)。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved