setwindowshookex (user32)
Last changed: -93.41.3.12

.
Summary
Installs a hook to monitor certain types of events.

C# Signature:

[DllImport("user32.dll")]
static extern IntPtr SetWindowsHookEx(HookType hook, HookProc callback,
   IntPtr hMod, uint dwThreadId);

VB Signature:

<DllImport("user32.dll")> _
Public Shared Function SetWindowsHookEx( _
     ByVal idHook As Integer, _
     ByVal lpfn As HookProc, _
     ByVal hMod As IntPtr, _
     ByVal dwThreadId As Integer) As IntPtr
End Function

User-Defined Types:

A HookType constant specifying the type of hook to install.

A HookProc delegate representing the hook procedure method.

Notes:

This will enable you to install application hooks. However, you cannot implement global hooks in Microsoft .NET Framework. To install a global hook, a hook must have a native dynamic-link library (DLL) export to inject itself in another process that requires a valid, consistent function to call into. This requires a DLL export, which .NET Framework does not support. Managed code has no concept of a consistent value for a function pointer because these function pointers are proxies that are built dynamically.

Tips & Tricks:

Remember to keep the HookProc delegate alive manually, otherwise the garbage collector will clean up your hook delegate eventually, resulting in your code throwing a System.NullReferenceException.

Sample Code:

// this sample installs a keyboard hook

using System.Windows.Forms;
public class MyClass
{
     private HookProc myCallbackDelegate = null;

     public MyClass()
     {
     // initialize our delegate
     this.myCallbackDelegate = new HookProc(this.MyCallbackFunction);

     // setup a keyboard hook
     SetWindowsHookEx(HookType.WH_KEYBOARD, this.myCallbackDelegate, IntPtr.Zero, AppDomain.GetCurrentThreadId());
     }

     [DllImport("user32.dll")]
     protected static extern IntPtr SetWindowsHookEx(HookType code, HookProc func, IntPtr hInstance, int threadID);

     private void MyCallbackFunction(int code, IntPtr wParam, IntPtr lParam)
     {
     // we can convert the 2nd parameter (the key code) to a System.Windows.Forms.Keys enum constant
     Keys keyPressed = (Keys)wParam.ToInt32();
     Console.WriteLine(keyPressed);
     }
}

Alternative Managed API:

Do you know one? Please contribute it!

Documentation
Example
Article