Java Windows低级密钥挂钩停止工作-不是超时问题
问题Java Windows低级密钥挂钩停止工作-不是超时问题,java,hook,jna,Java,Hook,Jna,问题 我正在实现一个Java程序,它通过JNA使用一个低级键钩子。在最初的几次运行中,一切正常,但在一些运行之后,挂钩停止工作,只有在我重新启动计算机时才能再次工作。 -附加细节:在这种情况下,“停止工作”意味着钩子检测到第一个按键下降事件,而没有其他事件(甚至是相应的按键上升事件) 已尝试的潜在根本原因 1-钩子超时->显然,Windows 7存在一些无法解释的行为,Windows通过这些行为删除钩子。如果是这样的话,重启应用程序和钩子会“压迫”它,但事实并非如此。 2-钩子过多->起初,我没
我正在实现一个Java程序,它通过JNA使用一个低级键钩子。在最初的几次运行中,一切正常,但在一些运行之后,挂钩停止工作,只有在我重新启动计算机时才能再次工作。
-附加细节:在这种情况下,“停止工作”意味着钩子检测到第一个按键下降事件,而没有其他事件(甚至是相应的按键上升事件) 已尝试的潜在根本原因
1-钩子超时->显然,Windows 7存在一些无法解释的行为,Windows通过这些行为删除钩子。如果是这样的话,重启应用程序和钩子会“压迫”它,但事实并非如此。
2-钩子过多->起初,我没有从以前的运行中删除钩子。现在我只在移除挂钩后才结束应用程序,但问题仍然存在 代码
[...]
public static void start() {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
lib = User32.INSTANCE;
HMODULE hMod = Kernel32.INSTANCE.GetModuleHandle(null);
ll = new MyLowLevelKeyboardProc();
hook = lib.SetWindowsHookEx(WinUser.WH_KEYBOARD_LL, ll, hMod, 0);
// We must maintain this code to keep the listener thread alive
MSG msg = new MSG();
while (lib.GetMessage(msg, null, 0, 0) != 0) {
System.out.println("cycle");
}
finish();
}
});
}
[...]
static class MyLowLevelKeyboardProc implements LowLevelKeyboardProc {
@Override
public LRESULT callback(int nCode, WPARAM wParam, KBDLLHOOKSTRUCT info) {
if (nCode >= 0) {
switch (wParam.intValue()) {
case WinUser.WM_SYSKEYUP:
case WinUser.WM_KEYUP:
System.out.println("KEY_UP");
if (AppConfig.DEBUG_MODE) {
if (info.vkCode == WindowsKeys.WK_Q.value()) {
finish();
System.exit(0);
}
}
default:
break;
}
}
return lib.CallNextHookEx(hook, nCode, wParam, info.getPointer());
}
public static void finish() {
if (lib != null) {
lib.UnhookWindowsHookEx(hook);
}
}
关键是在钩子里尽量少做。设置一个标志,然后在不同的线程上执行
System.exit()
调用。在JNA中,安装新的钩子时,通常应该调用以前的钩子。我怀疑这是您的问题的原因,但建议您这样做。包括您的注销代码。这可能就是你的问题所在。非常感谢你的快速回复,Technomage。我已经在打下一个钩子了(我怀疑这是否是你所说的“前一个钩子”,如果我误解了你,请纠正我)。我包括了下一个钩子调用和注销过程的代码。从钩子中调用System.exit()
可能是不可取的(或者除了存储数据之外,执行很多其他操作)。您可以尝试简单地设置一个标志,让另一个线程处理钩子的移除和清理。如果您担心钩子在此期间被调用,它可以保存一个内部禁用标志。谢谢,Technomage!现在它工作得很好!我更改了您指出的内容和其他细节(例如,使用Thread.start()而不是SwingUtilities.invokeLater()),以使代码更接近您提供的示例。