我正在开发一个使用键盘钩子的程序。但是,当程序运行的PC稍微过载时,它会导致Windows断开挂钩与程序的连接,导致它不再响应击键。
有没有办法阻止这种情况,甚至更好,通过使用不同的架构,可能涉及管道,提出一种解决完全相同问题的不同方法?
答案 0 :(得分:16)
你无法“发现”这一点,你绝对不应该这样做。您所描述的是一项功能,特别是在Windows 7中引入的功能,以保护您的系统免受恶意应用程序的侵害。
applicable documentation因此对其进行了描述(特别注意粗体部分):
钩子过程应该在比以下注册表项中的
LowLevelHooksTimeout
值中指定的数据条目更短的时间内处理消息:HKEY_CURRENT_USER\Control Panel\Desktop
该值以毫秒为单位。如果挂钩过程超时,系统会将消息传递给下一个挂钩。但是,在Windows 7及更高版本中,会在不调用的情况下以静默方式删除挂钩。应用程序无法知道钩子是否被移除。
这里的解决方案肯定是不,以找出卸载挂钩并重新安装它时“检测”的方法。当操作系统首次卸载时
时,你应该已经知道你做错了什么。实际的解决方案是重新设计您的应用程序,以便更快地从钩子程序返回。理想情况下,您应该立即返回。如果你需要运行某种类型的密集计算以响应低级别的消息(我无法想象你为什么会这样做),那么你应该存储你收到的信息,从钩子程序返回,然后在稍后(可能在一个单独的线程上)。
事实上,这几乎完全文档继续建议:
注意:调试挂钩无法跟踪此类低级键盘挂钩。如果应用程序必须使用低级别挂钩,它应该在专用线程上运行挂钩,该挂钩将工作传递给工作线程然后立即返回。在大多数应用程序需要使用低级别挂钩的情况下,它应该监视原始输入。这是因为原始输入可以异步监视与低级别挂钩相比更有效地针对其他线程的鼠标和键盘消息。有关原始输入的更多信息,请参阅Raw Input。
答案 1 :(得分:3)
我不太确定键盘挂钩总是要受到责备。我们似乎都同意,在理想或平均条件下,一切都应该是响应性的。但是在从启动到关闭的整个生命周期中,钩子也必须在最坏情况下生存。在我的公司,我们编写了一些键盘钩子,它们尽可能轻量级和异步,但它们偶尔会出现断线。
作为用户,我每天都会键入几万个字符。我最多每月重启一次,有时我会跳过Windows Update。有了suspend和hibernate等选项,我觉得我并不孤单。作为一名开发人员,我必须确保钩子始终从头到尾运行,无论系统发生什么。
通常我的系统反应灵敏。但是可以有短暂的,特殊的时刻,即使是Windows Aero也会被关闭。现在它非常活泼。但是,如果按下“显示桌面”按钮,鼠标将在我的65个左右打开的窗口全部折叠期间冻结至少一秒钟。如果我在其中一个时刻按下键怎么办?
如果Windows可以将鼠标冻结一秒钟,如果Windows甚至可以在重负荷的短暂时刻关闭Aero,为什么键盘挂钩不能在类似的异常超载时间内存活?相反,由于一个特殊时刻,Windows拉动插头,默默地影响剩余的计算体验,直到系统关闭。我们每天都按下数千个只有一个按键的200毫秒,因为只有这一小时,用户必须重新启动系统,因为这是我理解的唯一方法会带回键盘宏或任何实用程序我依靠我的富有成效的工作。
即使确保阻止上述情况(最坏情况经验似乎并非如此),我也不确定一切都可以在一个单独的线程中轻松完成。例如,假设用户设置了一个用于启动应用程序的热键。是否有理由从当前上下文(前台窗口,权限等)启动应用程序?并且用户实际期望并接受延迟是不合理的,因为他知道,使用键盘,他刚开始需要更长时间的东西?我不知道这个例子在技术上是否合理,但我想说明一下,由于已知的事件,有时可能不可接受的事情是可以接受的。
键盘挂钩对于很多东西都非常有用,从宏到错误纠正到启动事物,Windows 7中引入的这种行为是好的和坏的,可接受的和不可接受的,平均的和特殊的,都是在同一个篮子里。这会伤害用户,因为高质量的键盘钩子可能会被杀死,开发人员也会受到伤害。想象一下,当你的应用程序没有正式解决方案在正常条件下运行良好,但在某些重负荷(或其他无法解释的情况)下被随机杀死时,支持噩梦是什么。
最后提出一个问题,是否有人知道Windows 8下的状态是什么,有什么变化吗?
答案 2 :(得分:2)
Cody Gray的反应非常好,但是FWIW,纯粹出于测试目的,您可能能够检测到断开连接的钩子。
当调用钩子proc时,将当前的滴答计数存储在主线程可访问的变量中。在主线程中,定期调用GetLastInputInfo
。它将为您提供系统中最后一个输入事件的滴答计数(不仅仅是在您的过程中)。如果GetLastInputInfo
提供的值明显晚于(比较新的)钩子进程滴答计数,那么很好地猜测钩子已断开连接。
答案 3 :(得分:0)
我认为你的钩子中有一些“性能不佳”的代码。这就是为什么会略微过载的原因。
“它导致Windows断开挂钩与程序”
你的钩子中是否有任何错误而你没有处理它?</ p>
AFAIK,如果它本身运行良好,Windows就不会断开它。
答案 4 :(得分:0)
尝试提高申请进程的优先级。