'HOOKPROC callback doesn't get called by the hook - C#
I'm trying to set a low-level keyboard hook. I have DLL with the following code:
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace InputListener;
public class LowLevelKeyboardHook : IDisposable
{
const int GLOBAL_HOOK = 0;
readonly HOOKPROC _callback;
readonly IntPtr _hHook;
public IntPtr Handle => _hHook;
public LowLevelKeyboardHook(HOOKPROC hookCallback, bool throwOnFail = false)
{
_callback = hookCallback;
IntPtr hHookProcModule;
using (var currentModule = Process.GetCurrentProcess().MainModule)
hHookProcModule = GetModuleHandle(currentModule);
_hHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, hHookProcModule, GLOBAL_HOOK);
var errorCode = GetLastError();
if (throwOnFail && hHookProcModule == IntPtr.Zero) throw new DllNotFoundException("The module where the callback defined could not be retrieved.");
if (throwOnFail && Handle == default) throw new Exception("The hook could not be set.");
}
static IntPtr GetModuleHandle(ProcessModule? module)
{
return GetModuleHandle(module?.ModuleName!); ;
}
IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0) _callback(nCode, wParam, lParam);
return CallNextHookEx(Handle, nCode, wParam, lParam);
}
[DllImport("Kernel32.dll", CharSet = CharSet.Unicode)]
extern static IntPtr GetModuleHandle(string lpModuleName);
[DllImport("Kernel32.dll")]
extern static int GetLastError();
[DllImport("User32.dll")]
extern static IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll")]
static extern IntPtr SetWindowsHookEx(int hookType, HOOKPROC lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("User32.dll")]
extern static bool UnhookWindowsHookEx(IntPtr hhk);
const int WH_KEYBOARD_LL = 0xD;
public void Dispose()
{
GC.SuppressFinalize(this);
UnhookWindowsHookEx(Handle);
}
}
public delegate IntPtr HOOKPROC(int nCode, IntPtr wParam, IntPtr lParam);
After including this DLL to a console application and running the following code, LowLevelKeyboardProc never gets called but errorCode holds 0 and all handles are returned:
Task.Run(() => {
var hook = new LowLevelKeyboardHook(TestProc);
while (true) ;
});
while (true) ;
IntPtr TestProc(int nCode, IntPtr wParam, IntPtr lParam)
{
Console.WriteLine("Works");
return default;
}
Please, help me with this one. I've spent a lot of time trying to figure out the reason why the callback doesn't get called. I peeked into the code of other people and they do virtually the same things I do but my code doesn't seem to work. Currently, I think that the issue might well be in the loop that I use for testing the hook. When I run the program.
Solution 1:[1]
Thanks to a couple of redditors I found out that the hook seems not to work because there is no message loop in console applications.
This hook is called in the context of the thread that installed it. The call is made by sending a message to the thread that installed the hook. Therefore, the thread that installed the hook must have a message loop.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | GualaBanana |
