VC底层钩子程序在Win7/Vista下无效

最近工作需要,用到了鼠标钩子,并且还是全局鼠标钩子,也就是说,这个钩子监视系统所有消息,因此启动这个功能后,发现程序性能有点受影响,这也是正常的。

但是,原本在xp上运行好好的,放到win7上进行测试,发现过段时间,钩子会自动无效掉,这个时候去人工卸载钩子会弹出无效句柄错误消息(Error Code: 1404)。

这个问题类似指针,指针开始时分配了内存,但过段时间后,指针与该内存切断了联系,但指针指向的值并不是NULL,这个时候去卸载(delete)操作,则肯定是非法的。

所以,反复在网上查找相关的资料和论坛,发现大家都认为要么是win7下权限问题(UAC,管理员身份运行),或者是全局钩子与dl有关的影响,又或者是新版本.Net不支持全局钩子(因为我使用C#调用API),再或者是钩子句柄应该放在代码段区域(code_seg)等等。

 

最后在msdn论坛上找到了解答:(Hooking problem in Windows 7

http://social.msdn.microsoft.com/Forums/en-US/windowscompatibility/thread/f6032ca1-31b8-4ad5-be39-f78dd29952da

大概意思就是:
Win7移除超时的钩子不是bug,而是win7中为了保护系统而故意的行为,因为安装了全局钩子后,所以消息都要经过这个钩子,并且等待钩子过程执行结束或者钩子达到超时时间才能处理其他的响应,严重影响性能。
其实在vista中已经加入了一些保护措施,但不是很充分,所以在win7加入了当底层钩子多次超时时,就由系统自动卸载掉该钩子。

所以,原因清楚了,方案有两个。
1.在win7系统中加入LowLevelHooksTimeout时间,如[HKEY_CURRENT_USER\Control Panel\Desktop]"LowLevelHooksTimeout"=dword:00002710
2.在安装钩子尽量在一个独立的线程中进行,并且钩子处理过程尽量用较短的时间,其他任何较长时间的处理都放在别的线程中异步处理。(尽量不要写花时间的hook代码)

View Code
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;
}

posted on 2012-06-21 16:44  ActiveChange  阅读(4841)  评论(2编辑  收藏  举报

导航