I recently wrote some code which needed to install a low-level global mouse hook. I promptly did a MSN search and came up with two good articles on the subject – a KB article and a MSDN mag article. So, I religiously copy-pasted the code from the KB article and it ran after giving a warning that AppDomain.GetCurrentThreadId()has been deprecated in .NET 2.0. But this was not a system hook, it was a local hook – as soon as my mouse pointer went out of my app’s bounds, it would keep mum.
So to get a system hook, I changed the WH_MOUSE to WH_MOUSE_LL. It simply refused to work with this – the hook wasn’t registering at all. Finally after hours of scratching around I found a blog by Stephen Toub where he uses global keyboard hook to write an add-in for Media Center. And it turns out that this call does the trick:
mouseHookHandle = SetWindowsHookEx(WH_MOUSE_LL, mouseHookCallBack,
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr GetModuleHandle(string lpModuleName);
Apparently I wasn’t passing the HInstance earlier. Raymond Chen has a blog entry explaining why HInstance needs to be passed. But here’s my pickle – since the WH_MOUSE_LL is not injected but is executed in the hook’s registerer’s context itself, shouldn’t the thread ID be of more importance than the HInstance? Any takers?