我有一个Python脚本,它收集有关我在Windows机器上的键盘和鼠标使用情况的统计信息。
我是通过windll.user32.SetWindowsHookExA(win32con.WH_MOUSE_LL, mouse_pointer, win32api.GetModuleHandle(None), 0)
进行设置的。我这样写,以便您可以看到我使用的API。它也可能是一个c ++程序。
它工作得非常好,但有一个例外:当我使用Android Studio编译应用程序时,我的Core i7有4个内核,在所有内核上最高可达100%,鼠标和操作系统一般都没有响应,这是一个Android Studio的已知问题。
通常当这么高的CPU负载发生几秒钟(4+)时,操作系统会分离WH_MOUSE_LL挂钩,好像它说"不,我们不&# 39;没时间给你,我们注销你"
我不会责怪Python,因为我还有一个名为PowerMixer的音量管理器,它显然也会注册一个鼠标钩子,以便它可以跟踪下方任务栏上的鼠标滚轮操作(explorer) .exe Shell_TrayWnd)和这个应用程序也失去了它在编译后使用鼠标钩子的能力。
此外,当我正在编辑并不断滚动滚轮(只是为了好玩)时,计算机开始发出哔哔声,就像在一个非常低级别的系统蜂鸣声中,然后键盘挂钩也会被取消注册。
我如何通过Windows API检测我的钩子是否已分离/取消挂钩?我不需要Python特定的答案,只是使用Win32 API处理此问题的正确信息。
SetWindowsHookEx documentation的备注部分说:
如果挂钩过程超时,系统会将消息传递给 下一个钩子。但是,在Windows 7及更高版本中,挂钩是静默的 删除没有被调用。应用程序无法使用 知道钩子是否被移除。
我在这里运气不好吗?
更新:几周后,我只是想告诉Hans Passan的建议工作得很好。我推荐这个。虽然10.000毫秒似乎有点高,但我已将其设置为此值并且没有负面影响。这是在几分钟内解决系统问题的方法。
答案 0 :(得分:2)
如果我的钩子分离/取消挂钩,我如何通过Windows API检测到?
没有直接方式来执行此操作,并且您自己的问题引用了支持它的MSDN文档:
如果挂钩过程超时,系统会将消息传递给下一个挂钩。但是,在Windows 7及更高版本中,挂钩会在不调用的情况下以静默方式删除。应用程序无法知道钩子是否被移除。
然而,间接方式可能是让您的钩子跟踪上次调用它,然后您的主应用程序/脚本可以定期调用GetLastInputInfo()
并比较该时间到您的跟踪时间。如果差异显着高于存储在注册表中的挂钩超时(请参阅documentation),那么您的挂钩可能已经消失可能是一个不错的选择。
以下MSDN博客解释了挂钩超时的详细信息:
Global hooks getting lost on Windows 7
但是,最重要的是,它指出:
我的建议是,应尽可能避免使用低级挂钩。如果您正在监视击键(而不是试图阻止它们),您可以通过原始输入获得键盘输入。这比钩子重量轻,不会影响其他应用的响应性,如果应用无响应,将不会关闭。
这与Microsoft在LowLevelMouseProc()
和LowLevelKeyboardProc()
文档中的建议相同:
如果应用程序必须使用低级别挂钩,它应该在专用线程上运行挂钩,该挂钩将工作传递给工作线程,然后立即返回。 在大多数应用程序需要使用低级别挂钩的情况下,它应该监视原始输入。这是因为原始输入可以异步监视与低级别挂钩相比更有效地针对其他线程的鼠标和键盘消息。有关原始输入的更多信息,请参阅Raw Input。