Question

subjective...HA

ok so i've been looking around the internetz for a reasonable solution to trapping multiple keystrokes and came accross a few solutions that use the same thing (keyboard hook). One soltuion used a native call to get the IntPtr of a process by name, and the other used LoadLibrary("User32.dll")

so i figured I would be "smart" and did this (with success)

IntPtr hInstance = Process.GetCurrentProcess().MainModule.BaseAddress;
callbackDelegate = new HOOKPROC(HookCallback);
hhook = SetWindowsHookEx(WH_KEYBOARD_LL, callbackDelegate, hInstance, 0);

as apposed to using this

IntPtr hInstance = LoadLibrary("User32.dll");
callbackDelegate = new HOOKPROC(HookCallback);
hhook = SetWindowsHookEx(WH_KEYBOARD_LL, callbackDelegate, hInstance, 0);

is one safer than the other? am I making a fatal error that isn't showing it's head?

Was it helpful?

Solution 2

EDIT: My original answer left the IntPtr.Zero option open, and gave the neccesary information to help you decide. I'm adding another quote from the docs, which discusses when not to use null:

An error may occur if the hMod parameter is NULL and the dwThreadId parameter is zero or specifies the identifier of a thread created by another process.

Since you're using 0 as the thread id (which means "all existing threads running in the same desktop as the calling thread", as per the docs), you should NOT be using null but Marshal.GetHINSTANCE instead.


I think you should be passing either IntPtr.Zero or Marshal.GetHINSTANCE(your current module)

According to these docs, the third argument (hMod) is -

A handle to the DLL containing the hook procedure pointed to by the lpfn parameter. The hMod parameter must be set to NULL if the dwThreadId parameter specifies a thread created by the current process and if the hook procedure is within the code associated with the current process.

Also as mentioned in this article ("Windows Hooks in the .NET Framework"),

The third argument should be the HINSTANCE handle of the DLL that contains the code for the filter function. Typically, this value is set to NULL for local hooks. Do not use the .NET null object, though; use the IntPtr.Zero expression, which is the correct counterpart for Win32 null handles. The HINSTANCE argument cannot be null for systemwide hooks, but must relate to the module that contains the hook code—typically an assembly. The Marshal.GetHINSTANCE static method will return the HINSTANCE for the specified .NET module.

Also, see this question.

OTHER TIPS

SetWindowsHookEx() requires a valid module handle. It uses it to figure out what DLL needs to be injected into other processes to make the hook work.

But that's only a requirement for global hooks. The two low-level hooks (WH_MOUSE_LL and WM_KEYBOARD_LL) are special, they don't require DLL injection. Windows calls the hook callback in your own process only. The sole requirement is that your thread pumps a message loop so that Windows can make the callback. Application.Run() is required.

Also the reason that you can make low-level hooks work in C#, the DLL used by global hooks cannot be written in a managed language because the injected process will not have the CLR loaded.

The quirk is that SetWindowsHookEx() checks if you passed a valid module handle but then doesn't actually use it for the low-level hooks. So any valid handle you pass will work. This quirk was fixed in Windows 7 SP1 btw, it no longer performs that check.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top