最近工作需要,用到了鼠標鈎子,並且還是全局鼠標鈎子,也就是說,這個鈎子監視系統所有消息,因此啟動這個功能后,發現程序性能有點受影響,這也是正常的。
但是,原本在xp上運行好好的,放到win7上進行測試,發現過段時間,鈎子會自動無效掉,這個時候去人工卸載鈎子會彈出無效句柄錯誤消息(Error Code: 1404)。
這個問題類似指針,指針開始時分配了內存,但過段時間后,指針與該內存切斷了聯系,但指針指向的值並不是NULL,這個時候去卸載(delete)操作,則肯定是非法的。
所以,反復在網上查找相關的資料和論壇,發現大家都認為要么是win7下權限問題(UAC,管理員身份運行),或者是全局鈎子與dl有關的影響,又或者是新版本.Net不支持全局鈎子(因為我使用C#調用API),再或者是鈎子句柄應該放在代碼段區域(code_seg)等等。
最后在msdn論壇上找到了解答:(Hooking problem in Windows 7)
大概意思就是:
Win7移除超時的鈎子不是bug,而是win7中為了保護系統而故意的行為,因為安裝了全局鈎子后,所以消息都要經過這個鈎子,並且等待鈎子過程執行結束或者鈎子達到超時時間才能處理其他的響應,嚴重影響性能。
其實在vista中已經加入了一些保護措施,但不是很充分,所以在win7加入了當底層鈎子多次超時時,就由系統自動卸載掉該鈎子。
所以,原因清楚了,方案有兩個。
1.在win7系統中加入LowLevelHooksTimeout時間,如[HKEY_CURRENT_USER\Control Panel\Desktop]"LowLevelHooksTimeout"=dword:00002710
2.在安裝鈎子盡量在一個獨立的線程中進行,並且鈎子處理過程盡量用較短的時間,其他任何較長時間的處理都放在別的線程中異步處理。(盡量不要寫花時間的hook代碼)

DWORD WINAPI mouseLLHookThreadProc(LPVOID lParam) { MSG msg; _hMouseLLHook = SetWindowsHookEx( WH_MOUSE_LL, .....); while(GetMessage(&msg, NULL, 0, 0) != FALSE) { TranslateMessage(&msg); DispatchMessage(&msg); } return 0; }