Wednesday, September 2, 2009

Hook windows messages.

Today I would like to talk about how in C# you can hook messages that come to the application. For this we use the SetWindowsHookEx function from user32.dll. The SetWindowsHookEx function installs an application-defined hook procedure into a hook chain. You would install a hook procedure to monitor the system for certain types of events. These events are associated either with a specific thread or with all threads in the same desktop as the calling thread. WH_GETMESSAGE installs a hook procedure that monitors messages posted to a message queue.


public static partial class HookManager
{
  
private const int WH_GETMESSAGE = 3;
  
private const int WM_KEYDOWN = 0x100;

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

  [DllImport(
"user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
  
private static extern int SetWindowsHookEx(int idHook, CallbackPtr lpfn, IntPtr hMod, int dwThreadId);

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

  [DllImport(
"kernel32.dll")]
  
public static extern int GetCurrentThreadId();


  
public static void Init()
  {
    
if (m_hHook != 0) return;

    m_callBack =
new CallbackPtr(CallBack);
    m_hHook = SetWindowsHookEx(WH_GETMESSAGE, m_callBack,
IntPtr.Zero, GetCurrentThreadId());
  }

  
public static void Dispose()
  {
    
if (m_hHook == 0) return;

    UnhookWindowsHookEx(m_hHook);
    m_hHook = 0;
  }

  
private static int CallBack(int code, IntPtr wParam, ref MSG lParam)
  {

   
if (lParam.msg == WM_KEYDOWN && !m_bInHook)
   {
    m_bInHook =
true;
    
try
    {
     ...
    }
    
catch (Exception ex)
    {
     m_log.Fatal(
"UNHANDLED!", ex);
    }
    
finally
    {
     m_bInHook =
false;
    }
   }

   
return CallNextHookEx(m_hHook, code, wParam, ref lParam);
  }

  
private static CallbackPtr m_callBack;
  
private delegate int CallbackPtr(int code, IntPtr wp, ref MSG lp);

  
private static int m_hHook;
  
private static bool m_bInHook = false;
}


* This source code was highlighted with Source Code Highlighter.

1 comment:

  1. I seem to get this error:

    'The type or namespace name 'MSG' could not be found'

    It doesnt like any lines with "reg MSG lParam"

    ReplyDelete