Sebastian
Windows keyboard hook (SetWindowsHookExA) doesn't get called.
Simplified version:
It's doing "something" - when the application is running, key presses have some delay. What it's not doing however, is actually calling the Hook method. Any pointers?
KeyboardListener.KeyPress += (key) =>
{
Console.WriteLine(Enum.GetName(key));
};
KeyboardListener.Listen();
await Task.Delay(-1);
public static unsafe partial class KeyboardListener
{
private const string User32 = "user32";
private const string Kernel32 = "kernel32";
private const int KeyboardId = 13;
private const int KeyDown = 0x0100;
[LibraryImport(User32, SetLastError = true)]
private static partial nuint SetWindowsHookExA(int idHook, delegate* unmanaged<int, nuint, nint, nint> lpfn, nuint hmod, uint dwThreadId);
[LibraryImport(User32, SetLastError = true)]
private static partial nint CallNextHookEx(nuint hhk, int nCode, nuint wParam, nint lParam);
[LibraryImport(User32, SetLastError = true)]
private static partial int UnhookWindowsHookEx(nuint hhk);
private static nuint _handle = 0;
public static event Action<ConsoleKey>? KeyPress;
public static void Listen()
{
nuint hmod = (nuint)Marshal.GetHINSTANCE(typeof(KeyboardListener).Module);
_handle = SetWindowsHookExA(KeyboardId, &Hook, hmod, 0);
}
public static void Stop()
{
UnhookWindowsHookEx(_handle);
}
[UnmanagedCallersOnly]
private static nint Hook(int nCode, nuint wParam, nint lParam)
{
if (nCode >= 0 && wParam == KeyDown)
{
ConsoleKey key = (ConsoleKey)lParam;
KeyPress?.Invoke(key);
}
return CallNextHookEx(0, nCode, wParam, lParam);
}
}
KeyboardListener.KeyPress += (key) =>
{
Console.WriteLine(Enum.GetName(key));
};
KeyboardListener.Listen();
await Task.Delay(-1);
public static unsafe partial class KeyboardListener
{
private const string User32 = "user32";
private const string Kernel32 = "kernel32";
private const int KeyboardId = 13;
private const int KeyDown = 0x0100;
[LibraryImport(User32, SetLastError = true)]
private static partial nuint SetWindowsHookExA(int idHook, delegate* unmanaged<int, nuint, nint, nint> lpfn, nuint hmod, uint dwThreadId);
[LibraryImport(User32, SetLastError = true)]
private static partial nint CallNextHookEx(nuint hhk, int nCode, nuint wParam, nint lParam);
[LibraryImport(User32, SetLastError = true)]
private static partial int UnhookWindowsHookEx(nuint hhk);
private static nuint _handle = 0;
public static event Action<ConsoleKey>? KeyPress;
public static void Listen()
{
nuint hmod = (nuint)Marshal.GetHINSTANCE(typeof(KeyboardListener).Module);
_handle = SetWindowsHookExA(KeyboardId, &Hook, hmod, 0);
}
public static void Stop()
{
UnhookWindowsHookEx(_handle);
}
[UnmanagedCallersOnly]
private static nint Hook(int nCode, nuint wParam, nint lParam)
{
if (nCode >= 0 && wParam == KeyDown)
{
ConsoleKey key = (ConsoleKey)lParam;
KeyPress?.Invoke(key);
}
return CallNextHookEx(0, nCode, wParam, lParam);
}
}
11 replies