Share via


Low-Level Global Hooks in .NET 2.0

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,

                  GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName), 0);

Of course,

        [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?

Comments

  • Anonymous
    March 12, 2006
    I did exactly as you suggested, but the hook still only runs when i have my app in focus. IE - It's not global.

  • Anonymous
    March 12, 2006
    to clarify that, it works when my mouse exits the sides of the form... but not if i take the focus away by clicking on another program.

  • Anonymous
    July 18, 2006
    When the focus is on another app then the mouse messages you recieve would correspond to that app.

  • Anonymous
    May 16, 2007
    According to the below URL: http://support.microsoft.com/kb/318804 Global hooks are not supported in the .NET Framework Except for the WH_KEYBOARD_LL low-level hook and the WH_MOUSE_LL low-level hook, you cannot implement global hooks in the Microsoft .NET Framework. To install a global hook, a hook must have a native DLL export to inject itself in another process that requires a valid, consistent function to call into. This behavior requires a DLL export. The .NET Framework does not support DLL exports. Managed code has no concept of a consistent value for a function pointer because these function pointers are proxies that are built dynamically. Low-level hook procedures are called on the thread that installed the hook. Low-level hooks do not require that the hook procedure be implemented in a DLL.

  • Anonymous
    October 04, 2007
    Change the WH_MOUSE constant from 7 to 14. I guess it makes it global

  • Anonymous
    December 03, 2011
    Marshal.GetHINSTANCE(Reflection.Assembly.GetExecutingAssembly().GetModules()(0))