views:

808

answers:

2

I am using SetWindowsHookEx() to create a keyboard hook. The creation seems to be successful but the procedure which is registered never gets called. Is there something I am doing wrong?

#region Windows API Functions Declarations

[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
private static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);

[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
private static extern bool UnhookWindowsHookEx(int idHook);

[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
private static extern int CallNextHookEx(int idHook, int nCode, IntPtr wParam, IntPtr lParam);

[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName);

#endregion

=

private void CreateHook()
{
   int id_hook = (int)HookType.WH_KEYBOARD_LL;
   HookProc lpfn = new HookProc(this.KeyboardHookProc);

   using (ProcessModule curModule = Process.GetCurrentProcess().MainModule)
      hHook = SetWindowsHookEx(id_hook, lpfn, GetModuleHandle(curModule.ModuleName), 0);

   if (hHook == 0)
      throw new Exception("could not start monitoring mouse events");
}

=

private int KeyboardHookProc(int code, IntPtr wParam, IntPtr lParam)
{
   if (code >= 0)
      Console.WriteLine((Keys)wParam.ToInt32());
   return CallNextHookEx(0, code, wParam, lParam);
}

=

+1  A: 

Your P/Invoke declarations are wrong, you are using int where IntPtr is required and mixing up idHook and hHook. After editing your code, this worked:

IntPtr hHook;
private delegate IntPtr HookProc(int nCode, IntPtr wp, IntPtr lp);
HookProc lpfn;

private IntPtr KeyboardHookProc(int code, IntPtr wParam, IntPtr lParam) {
  if (code >= 0)
    Console.WriteLine((Keys)wParam.ToInt32());
  return CallNextHookEx(hHook, code, wParam, lParam);
}

private void CreateHook() {
  int id_hook = 13;
  lpfn = new HookProc(this.KeyboardHookProc);
  using (ProcessModule curModule = Process.GetCurrentProcess().MainModule)
    hHook = SetWindowsHookEx(id_hook, lpfn, GetModuleHandle(curModule.ModuleName), 0);
  if (hHook == IntPtr.Zero)
    throw new Exception("could not start monitoring mouse events");
}
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
private static extern IntPtr SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
private static extern bool UnhookWindowsHookEx(IntPtr hHook);
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
private static extern IntPtr CallNextHookEx(IntPtr hHook, int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName);
Hans Passant
The functions seem to be doing something because when the function attaches to the keyboard loop, keyboard input will be delayed for a while, and when attaching to the mouse loop, mouse input will be slow for a while. But the KeyboardHookProc does not seem to be getting hit. I am using .NET 3.5 by the way.
Nippysaurus
A: 

Dude... You rockz my sockz. Thank you.

Miguel Mas
@Miguel: As a general rule, you should only create an answer if you're providing a solution - Otherwise, use the "Add Comment" link underneath a post. I haven't voted you down as you're new to the site but be aware others may. Regards
Basiclife