全域鉤子安裝後必須正確卸載,否則會導致系統資源洩漏、甚至影響其他程序穩定。本文詳細說明卸載流程、錯誤碼獲取與例外處理最佳實務。
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);
}
}
}
IntPtr.Zero 表示未安裝,避免重複卸載。hHook,成功回傳 true。throwExceptions = true:擲回 Win32Exception,攜帶 Windows 錯誤碼,適合開發除錯階段。throwExceptions = false:靜默失敗,適合生產環境關機流程,避免未處理例外導致程序崩潰。Marshal.GetLastWin32Error() 必須緊接在 P/Invoke 呼叫之後,否則可能被覆蓋。IDisposable,在 Dispose() 中呼叫 Stop(),確保資源釋放。SafeHandle 衍生類別封裝 hHook,利用 CLR 關鍵最終化機制雙重保障。Application.ApplicationExit、AppDomain.ProcessExit)務必卸載所有鉤子。正確卸載全域鉤子與安裝同等重要。遵循「檢查→卸載→歸零→錯誤處理」四步驟,並配合 IDisposable 模式,即能構建健壯的鍵盤攔截元件。