Windows低级别密钥挂钩停止工作 - 不是超时问题

时间:2015-02-18 18:08:09

标签: java hook jna

问题
我正在实现一个通过JNA使用低级别密钥钩子的Java程序。在前几次运行中一切正常,但是在一些运行之后,挂钩停止工作,只有在我重新启动计算机时才能再次工作 - 其他细节:'停止工作'在这种情况下意味着钩子检测到第一个按键事件而没有其他事件(甚至是相应的按键事件)

潜在的根本原因
1 - 挂机超时 - >显然,有一些原因不明的Windows 7行为,Windows通过这种行为删除了一个钩子。如果是这种情况,重新启动应用程序和钩子将重新确保'它 - 但那不是发生的事情。
2 - 钩子过多 - >起初,我没有从以前的运行中删除我的钩子。现在我只是在删除钩子后结束应用程序,但问题仍然存在。

CODE

[...]
    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);
        }
    }

1 个答案:

答案 0 :(得分:0)

关键是尽量少做钩子。设置一个标志,然后在另一个线程上执行System.exit()调用。