We have some global keyboard hooks installed via SetWindowsHookEx
with WH_KEYBOARD_LL
that appear to randomly get unhooked by Windows.
We verified that they hook was no longer attached because calling UnhookWindowsHookEx
on the handle returns false
. (Also verified that it returns true
when it was working properly)
There doesn't seem to be a consistent repro, I've heard that they can get unhooked due to timeouts or exceptions getting thrown, but I've tried both just letting it sit on a breakpoint in the handling method for over a minute, as well as just throwing a random exception (C#) and it still appears to work.
In our callback we quickly post to another thread, so that probably isn't the issue. I've read about solutions in Windows 7 for setting the timeout higher in the registry because Windows 7 is more aggressive about the timeouts apparently (we're all running Win7 here, so not sure if this occurs on other OS's) , but that doesn't seem like an ideal solution.
I've considered just having a background thread running to refresh the hook every once in a while, which is hackish, but I don't know of any real negative consequences of doing that, and it seems better than changing a global Windows registry setting.
Any other suggestions or solutions? Both the class that sets the hooks and the delegates they are attached to are static, so they shouldn't be getting GC'd.
EDIT: Verified with calls to GC.Collect();
that they still work, so they are not getting garbaged collected.
Application.Run
and unhooked right after. – SilicicSystem.Threading.Thread.Sleep()
in your hook callback? Could be a long shot, but using an IDE breakpoint might not be an exact representation of a blocked hook callback. – PurushaGlobalHooks.InstallHooks(); Application.Run(mainForm); GlobalHooks.UninstallHooks();
which call all theSetWindowsHookEx
andUnhookWindowsHookEx
respectively. If the thread dies, the application should also close since it's all on the Main thread. – SilicicSystem.Threading.Thread.Sleep(10000);
to the callback and it still works. We're definitely not blocking over 10 seconds, should be way less than 1/4 second. – SilicicGC.Collect();
and they still work. – Silicic