Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

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.

like image 585
Davy8 Avatar asked Apr 16 '10 18:04

Davy8


People also ask

What is a keyboard hook?

A hook is a mechanism by which an application can intercept events, such as messages, mouse actions, and keystrokes. A function that intercepts a particular type of event is known as a hook procedure.

What is hook in Windows?

A hook is a point in the system message-handling mechanism where an application can install a subroutine to monitor the message traffic in the system and process certain types of messages before they reach the target window procedure.


1 Answers

I think this has to be a timeout issue.

Other developers have reported a Windows7 specific problem with low level hooks being unhooked if they exceed an (undocumented) timeout value.

See this thread for other developers discussing the same problem. It may be that you need to perform a busy loop (or a slow Garbage Collection) rather than a Sleep to cause the unhooking behavior. A breakpoint in the LowLevelKeyboardProc function might also create timeout problems. (There's also the observation that a heavy CPU load by another task might provoke the behavior - presumably because the other task steals CPU cycles from the LowLevelKeyboardProc function and causes it to take too long.)

The solution suggested in that thread is to try setting the LowLevelHooksTimeout DWORD value in the registry at HKEY_CURRENT_USER\Control Panel\Desktop to a larger value.

Remember that one of the glories of C# is that even simple statements can take an inordinate amount of time if a garbage collection occurs.. This (or CPU loading by other threads) might explain the intermittent nature of the problem.

like image 186
MZB Avatar answered Sep 29 '22 20:09

MZB