What can cause Windows to unhook a low level (global) keyboard hook?

后端 未结 7 1778
-上瘾入骨i
-上瘾入骨i 2020-12-13 14:19

We have some global keyboard hooks installed via SetWindowsHookEx with WH_KEYBOARD_LL that appear to randomly get unhooked by Windows.

We

7条回答
  •  清歌不尽
    2020-12-13 14:42

    Very late but thought i'd share something. Gathering from here there's a couple hints like putting the SetWindowsHookEx in a separate thread and that it's more a scheduling problem.

    I also noticed that Application.DoEvents was using quite a bit of CPU, and found that PeekMessage uses less.

    public static bool active = true;
    
    [StructLayout(LayoutKind.Sequential)]
    public struct NativeMessage
    {
        public IntPtr handle;
        public uint msg;
        public IntPtr wParam;
        public IntPtr lParam;
        public uint time;
        public System.Drawing.Point p;
    }
    
    [SuppressUnmanagedCodeSecurity]
    [return: MarshalAs(UnmanagedType.Bool)]
    [DllImport("User32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern bool PeekMessage(out NativeMessage message,
        IntPtr handle, uint filterMin, uint filterMax, uint flags);
    public const int PM_NOREMOVE = 0;
    public const int PM_REMOVE = 0x0001;
    
    protected void MouseHooker()
    {
        NativeMessage msg;
    
        using (Process curProcess = Process.GetCurrentProcess())
        {
            using (ProcessModule curModule = curProcess.MainModule)
            {
                // Install the low level mouse hook that will put events into _mouseEvents
                _hookproc = MouseHookCallback;
                _hookId = User32.SetWindowsHookEx(WH.WH_MOUSE_LL, _hookproc, Kernel32.GetModuleHandle(curModule.ModuleName), 0);
            }
        }
            while (active)
            {
                while (PeekMessage(out msg, IntPtr.Zero,
                    (uint)WM.WM_MOUSEFIRST, (uint)WM.WM_MOUSELAST, PM_NOREMOVE))
                    ;
                Thread.Sleep(10);
            }
    
            User32.UnhookWindowsHookEx(_hookId);
            _hookId = IntPtr.Zero;            
    }
    
    public void HookMouse()
    {
        active = true;
        if (_hookId == IntPtr.Zero)
        {
            _mouseHookThread = new Thread(MouseHooker);
            _mouseHookThread.IsBackground = true;
            _mouseHookThread.Priority = ThreadPriority.Highest;
            _mouseHookThread.Start();
        }
    }
    

    so just change the active bool to false in Deactivate event and call HookMouse in the Activated event.

    HTH

    EDIT: I noticed games were slowed down with this, so decided to unhook when app is not active using Activated and Deactivate events.

提交回复
热议问题