读书人

允许与桌面交互的服务里调用SetWindow

发布时间: 2012-03-06 20:47:55 作者: rapoo

允许与桌面交互的服务里调用SetWindowsHookEx挂钩一个窗体,失败!
工作中需要在服务里调用SetWindowsHookEx挂钩一个窗体(线程钩子,不做全局钩子,太影响性能),但总是返回NULL,用GetLastError得到错误号5:ERROR_ACCESS_DENIED。我找遍了网上所有的资料,都说只要服务能与桌面交互即可。我在
CreateService中已经设置SERVICE_INTERACTIVE_PROCESS,安装完后用services.msc看我的服务属性,登录身份是本地系统账户,下面的“允许服务与桌面交互”前面的勾已经自动勾上了。但一调用SetWindowsHookEx就报错(我将错误号打印到文件以方便查看)。用GetThreadDesktop和GetUserObjectInformation查看服务线程和目的窗体线程的桌面,都是“Default”。我快疯掉了,痛苦求助中……
附:我的系统环境是XP SP2,在2K下试也不行。同样的错误。

[解决办法]
做不到,同一个帐户设置的钩子(无论全局还是本地)对其它帐户进程或窗口无效,即使设置了SERVICE_INTERACTIVE_PROCESS也没用。因为即使该服务能在当前桌面显示窗口,该窗口(进程)的权限还是system,并未提升权限到桌面所属帐户。

另,SERVICE_INTERACTIVE_PROCESS这个标志并不可靠,微软并不推荐使用这个标志,并明确说明以后的操作系统版本可能取消这个标志。

你要做的事情是:单独创建一个EXE程序,放到开始菜单或者注册表的RUN键下,用户登录桌面之后自动运行,此时设置钩子才能有效。
[解决办法]
我觉得应该换一种想法去解决这个问题:
楼主的钩子是放在一个DLL里面的。。

我建议:
1:可以不使用钩子来安装这个DLL啊。。可以使用远程线程注入到目标进程。
2:使用子类化,先查找目标窗口的句柄,然后用SetWindowLong进行子类化,那么你就可以完全截取那个窗口的消息了,而且也不是全局钩子,效率高。
3:代码改动量也不大,你的服务EXE只要在后台等待那个被HOOK的进程启动而已。也就省了切换桌面的麻烦任务。

读书人网 >VC/MFC

热点推荐