是否有可能检测到低级键盘钩子何时被Windows自动断开连接?

本文关键字:Windows 断开 连接 何时 检测 有可能 键盘 是否 | 更新日期: 2023-09-27 18:02:16

我正在编写一个使用键盘钩子的程序。但是,当该程序运行的PC只是稍微超载时,它会导致Windows断开该程序的钩子,导致它不再响应击键。

是否有一种方法可以防止这种情况,或者甚至更好,提出一种不同的方法来解决完全相同的问题,通过使用不同的体系结构,可能涉及管道?

是否有可能检测到低级键盘钩子何时被Windows自动断开连接?

你不能"detect"这个,你完全不需要。你所描述的是一个功能,特别是在Windows 7中引入的一个功能,用来保护你的系统免受恶意应用程序的攻击。

适用的文档这样描述它(特别注意加粗的部分):

钩子子程处理消息的时间应该少于以下注册表项中LowLevelHooksTimeout值指定的数据条目的时间:

HKEY_CURRENT_USER'Control Panel'Desktop

单位为毫秒。如果钩子子程超时,系统将消息传递给下一个钩子。然而,在Windows 7和更高版本上,钩子在不被调用的情况下被静默地删除。应用程序无法知道钩子是否被删除。

这里的解决方案肯定是而不是找出一种方法来"检测";将吊钩卸下后重新安装。当操作系统第一次卸载钩子时,你应该发现你做错了什么。

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

事实上,这几乎就是文档继续建议的:

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

我不太确定键盘挂钩总是罪魁祸首。我们似乎都同意,在理想或平均条件下,一切都应该有反应。但是在从启动到关闭的整个生命周期中,钩子还必须经受住一些最坏的情况。在我的公司,我们编写了一些键盘钩子,它们尽可能轻量级和异步,但它们仍然偶尔出现断开连接。

作为一个用户,我每天要打好几万个字。我最多一个月重启一次,有时我也会因为跳过Windows更新而感到内疚。有了暂停和休眠等选项,我想我并不孤单。作为一名开发人员,我必须确保钩子从头到尾一直运行,不管系统发生了什么。

通常我的系统反应很灵敏。但也会有短暂而特殊的时刻,它会跪在地上,甚至连Windows Aero都要关机了。现在它非常时髦。但如果我按下"显示桌面"按钮,鼠标会冻结至少一秒钟,因为我的65个左右打开的窗口都崩溃了。如果我在其中一个时刻按了一个键呢?

如果Windows可以冻结鼠标一秒钟,如果Windows甚至可以在负载过重的短暂时刻关闭Aero,为什么不能允许键盘钩子在类似的超负荷时间内存活下来?相反,由于一个异常时刻,Windows拔掉插头,默默地影响剩余的计算体验,直到系统关闭。在200毫秒的时间里,我们每天要按几千个键,只有一个键受到影响,在那不到一秒钟的时间里,我,用户,必须重新启动系统,因为这是我唯一能理解的恢复键盘宏或其他我所依赖的高效工作工具的方法。

即使它保证可以防止上述情况(最坏的情况似乎表明情况并非如此),我也不确定所有事情都可以在单独的线程中轻松完成。例如,假设用户设置了一个热键来启动应用程序。从当前上下文(前台窗口、特权等)启动应用程序不能有原因吗?用户期待并接受延迟难道不是合理的吗,因为他知道,使用键盘,他只是开始了一些需要更长时间的事情?我不知道这个例子在技术上是否合理,但我想说明,作为已知事件的结果,有时可能不可接受的事情可能是可以接受的。

键盘钩子在很多方面都非常有用,从宏到纠错到启动程序,Windows 7中引入的这种行为将好的和坏的,可接受的和不可接受的,一般的和特殊的,都放在一个篮子里。这对用户和开发者都不利,因为高质量的键盘钩子可能会被扼杀。想象一下,当你没有正式的解决方案让你的应用程序在正常情况下正常工作,但在一些繁重的负载(或其他无法解释的)情况下被随机杀死时,这是多么可怕的支持。

用一个问题来总结,有人知道Windows 8下的状态是什么吗,有什么变化吗?

Cody Gray的响应非常出色,但是,对于和纯粹出于测试目的的,您可能能够检测到断开连接的钩子。

当钩子进程被调用时,将当前tick计数存储在主线程可访问的变量中。在主线程中,定期调用GetLastInputInfo。它将为您提供系统(而不仅仅是流程)中最后一个输入事件的滴答计数。如果GetLastInputInfo提供的值明显晚于(更新)您的上一个钩子进程滴答计数,这是一个很好的猜测,钩子已被断开。

我认为你的钩子中有一些"性能差"的代码。这就是为什么会产生轻微过载的原因。

"它导致Windows从程序断开钩子"

钩子中是否有错误引发而你没有处理它?

我敢说,Windows不会断开钩子,如果它自己工作良好。

尝试增加应用程序进程的优先级。