是否有可能检测到Windows的低级键盘挂钩已被自动断开连接?

我正在使用一个使用键盘钩子的程序。 但是,当运行程序的PC稍微超载时,会导致Windows从程序中断开连接,导致它不再响应按键。

有没有办法通过使用不同的架构,可能涉及到一个pipe道,来防止这个问题,甚至更好地提出一种解决完全相同问题的不同方法?

你不能“察觉”这一点,你绝对不应该需要。 你所描述的是一个功能,特别是在Windows 7中引入的功能,以保护您的系统免受流氓应用程序的侵害。

适用的文件如此描述(特别注意粗体部分):

挂钩过程应该在比以下注册表项中的LowLevelHooksTimeout值中指定的数据项更少的时间内处理消息:

 HKEY_CURRENT_USER\Control Panel\Desktop 

该值以毫秒为单位。 如果挂钩程序超时,系统将消息传递给下一个挂钩。 但是, 在Windows 7和更高版本中,挂钩将被静默移除而不被调用。 应用程序无法知道钩子是否被移除。

这里的解决方案当然不是找出卸载挂钩时“检测”的方法并重新安装。 当操作系统一次卸载时,你应该已经知道你做错了什么。

实际的解决方案是重新设计你的应用程序以更快地从挂钩程序返回。 理想情况下,你应该立即返回。 如果您需要针对低级别消息运行某种类型的密集型计算(并且我无法真正想象为什么您会这么做),那么您应该存储收到的信息,从挂钩程序返回,并在以后的时间(可能在一个单独的线程)。

事实上,这几乎正是文件继续建议的:

注意:调试钩子不能跟踪这种类型的低级别键盘钩子。 如果应用程序必须使用低级别的钩子,则它应该在专用线程上运行钩子,将工作传递给工作线程,然后立即返回。 在大多数情况下,应用程序需要使用低级别的钩子,它应该监视原始输入。 这是因为原始输入可以异步地监视针对其他线程的鼠标和键盘消息,而不是低级别的钩子。 有关原始输入的更多信息,请参阅原始输入 。

科迪·格雷的反应非常好,但FWIW, 纯粹为了测试目的 ,你可能能够检测到一个断开连接的钩子。

当您的钩子程序被调用时,将当前的滴答计数存储在主线程可访问的变量中。 在主线程中,定期调用GetLastInputInfo 。 它会给你在系统中最后一个输入事件的滴答计数(不只是在你的过程中)。 如果GetLastInputInfo提供的值比最后一个钩子处理器滴答计数要晚得多(更新),那么钩子已经断开是一个很好的猜测。

我不太确定键盘钩总是要怪的。 我们似乎都同意,在理想或平均条件下,一切都应该是有回应的。 但是,在从启动到关闭的一生中,一个钩子也必须在一些最坏的情况下生存下来。 在我的公司,我们写了一些键盘钩子,它们尽可能的轻量级和异步,但是偶尔它们看起来会断开连接。

作为一个用户,我每天输入几万个字符。 我每个月至少重新启动一次,偶尔我会跳过Windows更新。 像暂停和休眠的选项,我不认为我是孤独的。 作为开发人员,我必须确保挂钩始终运行,无论系统发生什么情况。

通常我的系统是非常敏感的。 但是,即使Windows Aero被关闭,也可能出现短暂的,特殊的时刻。 现在它非常活泼。 但是,如果我按下“显示桌面”按钮,在我的65个左右打开的窗口全部折叠的时候,鼠标将冻结至少一秒。 如果我在这个时候按下某个键,该怎么办?

如果Windows可以将鼠标冻结一秒钟,如果Windows在重负载的短时间内甚至可以关闭Aero,那么为什么不能允许键盘钩子在类似的过载时间内存活呢? 相反,由于一个特殊的时刻,Windows拔下插头,直到系统关闭,静静地影响剩余的计算体验。 对于200毫秒的影响只是我们每天按下的数千个按键中的一小部分,我用户必须重新启动系统,因为这是我理解的唯一方法就是将键盘宏或任何实用程序我依靠我的生产性工作。

即使这样做是有保障的(最糟糕的经验似乎并不是这样),但我不确定一切都可以轻易地在一个单独的线程中完成。 例如,假设用户设置了启动应用程序的热键。 难道没有理由从当前上下文(前台窗口,权限等)启动应用程序吗? 用户是否真的期待和接受延迟是不合理的,因为他知道,使用键盘,他开始需要更长的时间? 我不知道这个例子在技术上是否正确,但是我想说明一下,有时事情可能是不可接受的,作为已知事件的结果是可以接受的。

键盘钩子对于很多事情来说是非常有用的,从宏到错误修正到启动东西,而在Windows 7中引入的这种行为是好的和坏的,可接受的和不可接受的,平均和异常的,都在相同的篮。 这伤害了两个用户,因为高质量的键盘钩子可能会被杀死,而开发人员。 试想一下,如果你的应用程序没有正式的解决方案,在正常情况下运行良好,但在一些重负载(或其他莫名其妙的)情况下被随机杀死,那么支持什么样的恶梦呢?

总结这个问题,有没有人知道什么是Windows 8下的状态,有什么改变?

我认为你的钩子里有一些“糟糕的表现”的代码。 这就是为什么稍微超载的原因。

“它导致Windows断开与程序挂钩”

你的钩子有没有出现错误,你不处理?

AFAIK,如果Windows本身运行良好,Windows将不会断开连接。