【发布时间】:2010-04-16 18:22:16
【问题描述】:
我们通过SetWindowsHookEx 和WH_KEYBOARD_LL 安装了一些全局键盘挂钩,这些挂钩似乎会被Windows 随机解除挂钩。
我们验证了它们的钩子不再附加,因为在句柄上调用 UnhookWindowsHookEx 会返回 false。 (还验证了它在正常工作时返回true)
似乎没有一致的重现,我听说它们可能会由于超时或抛出异常而脱钩,但我已经尝试过两种方法都只是让它在处理方法中的断点上停留一段时间一分钟,以及只是抛出一个随机异常(C#),它似乎仍然有效。
在我们的回调中,我们快速发布到另一个线程,所以这可能不是问题。我已经阅读了 Windows 7 中有关在注册表中设置更高超时的解决方案,因为 Windows 7 显然对超时更具侵略性(我们都在这里运行 Win7,所以不确定这是否发生在其他操作系统上),但这并没有这似乎不是一个理想的解决方案。
我考虑过只运行一个后台线程以每隔一段时间刷新一次钩子,这很骇人听闻,但我不知道这样做有什么真正的负面后果,而且这似乎比更改全局更好Windows 注册表设置。
还有其他建议或解决方案吗? 设置钩子的类和它们所附加的委托都是静态的,因此它们不应该被 GC 处理。
编辑:通过调用GC.Collect(); 验证它们仍然有效,因此它们不会被垃圾收集。
【问题讨论】:
-
让 SetWindowsHookEx 调用退出或终止的线程会执行此操作。
-
@Hans 这不是给我们的,但它可以帮助其他人。他们在
Application.Run之前被连接起来,之后就被解开。 -
我似乎记得托管线程与非托管线程不是 1:1 的。也许非托管线程终止了?
-
就超时而言,您是否在钩子回调中尝试过
System.Threading.Thread.Sleep()?可能是一个很长的镜头,但使用 IDE 断点可能不能准确表示阻塞的钩子回调。 -
@Zach 尝试在回调中添加
System.Threading.Thread.Sleep(10000);,但它仍然有效。我们绝对不会阻塞超过 10 秒,应该少于 1/4 秒。
标签: c# keyboard-hook setwindowshookex