4

I've been looking into low level keyboard hooks lately. I have already got mine working but I have some questions on the code.

I see there is a complete code for Console application here: http://blogs.msdn.com/b/toub/archive/2006/05/03/589423.aspx

In the Main function, I see the programmer called a "UnhookWindowsHookEx" DLL function. What is the purpose of this function and what would happen if it is commented out? (Bad consequences especially?)

EDIT:

And one more thing. Why must "Application.Run()" be called in order for the code to work?

Felastine
  • 793
  • 2
  • 8
  • 18

3 Answers3

3
  1. In this particular case, if UnhookWindowsHookEx is commented, nothing bad happens, because the program exits anyway. But it is a good idea to close any resource when it is not required anymore, both when the program continues executing, and in the end of the program - to keep resources usage under the control.

  2. Without Application.Run the program exits immediately. The second reason for using Application.Run is SetWindowsHookEx requirement - it needs message loop to work. Application.Run executes the message loop. Program may be stopped by pressing Ctrl+C.

Alex F
  • 42,307
  • 41
  • 144
  • 212
  • How does this code compare with the use of RegisterHotkey? [link]http://stackoverflow.com/questions/11570513/low-level-keyboard-hook. From this post, it sounds that they both serve the same purpose. – Felastine Oct 03 '12 at 09:20
  • WH_KEYBOARD_LL allows to hide some keyboard messages from another programs, if it doesn't call CallNextHookEx. – Alex F Oct 03 '12 at 09:53
2

It is not strictly necessary to call UnhookWindowsHookEx(), Windows does figure out that you forgot to do so and will unhook when your program terminates. Necessarily so, not cleaning up the hook would cause Windows to hang. It is considered "good manners" to not leave it up to the operating system.

The Application.Run() call is a hard requirement for a program that implements a low-level hook. Without a message loop, say using Console.ReadLine() instead, the callbacks to the hook are not made. The specific Windows promise is that the callback will be made on the same thread that called SetWindowsHookEx(). To do that, Windows somehow has the "break in" and force your thread to call the callback method. It can't just arbitrarily interrupt your thread and force it to make the call, that would cause horrible re-entrancy problems. Your thread has to be in a well defined state, it has to be idle and not mutating program state.

The message loop, specifically the GetMessage() or PeekMessage() winapi function, is that signal, when your thread pumps the message loop then it is idle and waiting for Windows to tell it to do something. It is the universal solution to the producer/consumer problem.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
2

No, it's bad.

Native hooks are not 'handles' in the same sense as file or process handles. They're persistent for the Windows session and the resource is scarce.

I try to call it whenever possible, but I'm often forced terminate my because it hangs or something, and after two dozen or so times the hooks fails to register.

All other applications that use hooks, like some games, will also fail after this. The only solution appears to be reboot.

Mark Jeronimus
  • 9,278
  • 3
  • 37
  • 50