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

C# 使用全域鉤子實作螢幕鍵盤(四):安全卸載鉤子與錯誤處理

     編輯:關於C語言

前言

全域鉤子安裝後必須正確卸載,否則會導致系統資源洩漏、甚至影響其他程序穩定。本文詳細說明卸載流程、錯誤碼獲取與例外處理最佳實務。

完整卸載程式碼

public void Stop()
{
    Stop(true, true, true);
}

public void Stop(bool uninstallMouseHook, bool uninstallKeyboardHook, bool throwExceptions)
{
    // 卸載滑鼠鉤子
    if (hMouseHook != IntPtr.Zero && uninstallMouseHook)
    {
        bool ret = UnhookWindowsHookEx(hMouseHook);
        hMouseHook = IntPtr.Zero;

        if (!ret && throwExceptions)
        {
            int errorCode = Marshal.GetLastWin32Error();
            throw new Win32Exception(errorCode);
        }
    }

    // 卸載鍵盤鉤子
    if (hKeyboardHook != IntPtr.Zero && uninstallKeyboardHook)
    {
        bool ret = UnhookWindowsHookEx(hKeyboardHook);
        hKeyboardHook = IntPtr.Zero;

        if (!ret && throwExceptions)
        {
            int errorCode = Marshal.GetLastWin32Error();
            throw new Win32Exception(errorCode);
        }
    }
}

關鍵點解析

  1. 檢查控制代碼有效性:IntPtr.Zero 表示未安裝,避免重複卸載。
  2. 呼叫 UnhookWindowsHookEx:傳入安裝時取得的 hHook,成功回傳 true。
  3. 立即歸零控制代碼:防止後續誤用已釋放的鉤子。
  4. 錯誤處理策略:
    • throwExceptions = true:擲回 Win32Exception,攜帶 Windows 錯誤碼,適合開發除錯階段。
    • throwExceptions = false:靜默失敗,適合生產環境關機流程,避免未處理例外導致程序崩潰。
  5. 取得錯誤碼:Marshal.GetLastWin32Error() 必須緊接在 P/Invoke 呼叫之後,否則可能被覆蓋。

最佳實務建議

  • 實作 IDisposable,在 Dispose() 中呼叫 Stop(),確保資源釋放。
  • 使用 SafeHandle 衍生類別封裝 hHook,利用 CLR 關鍵最終化機制雙重保障。
  • 應用程式結束前(Application.ApplicationExit、AppDomain.ProcessExit)務必卸載所有鉤子。
  • 單元測試驗證安裝/卸載配對,防止記憶體洩漏。

結語

正確卸載全域鉤子與安裝同等重要。遵循「檢查→卸載→歸零→錯誤處理」四步驟,並配合 IDisposable 模式,即能構建健壯的鍵盤攔截元件。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved