今天,有个同事问我,怎样在C#中使用全局钩子?以前写的全局钩子都是用unmanaged C或C++写个DLL来实现,可大家都知道,C#是基于.Net Framework的,是managed,怎么实现全局钩子呢?于是开始到网上搜索,好不容易找到一篇,318804 - HOW TO: Set a Windows Hook in Visual C# .NET,里面详细的说明了如何使用鼠标钩子捕获鼠标的移动等,可是,它只能在Application里起作用,出了Application就没用了,就是说它还是没有实现全局钩子,而且文章结尾处说:“Global Hooks are not supported in the .NET Framework...”,这可怎么办呢?

  别担心,办法总是有的,经过一番摸索以后,发现WH_KEYBORAD_LL和WH_MOUSE_LL这两个low-level的hook可以被安装成全局的,这就好办了,我们不妨用这两个low-level的hook替换掉WH_KEYBORAD和WH_MOUSE,于是开始测试。结果成功了,在C#里实现了全局钩子。

  我们来看一下主要代码段。

  首先倒入所需要的windows函数,主要有三个,SetWindowsHookEX用来安装钩子,UnhookWindowsHookEX用来卸载钩子以及CallNextHookEX用来将hook信息传递到链表中下一个hook处理过程。

如何在C#中使用全局鼠标、键盘Hook[DllImport("user32.dll", CharSet = CharSet.Auto,
如何在C#中使用全局鼠标、键盘Hook           CallingConvention 
= CallingConvention.StdCall, SetLastError = true)]
如何在C#中使用全局鼠标、键盘Hook        
private static extern int SetWindowsHookEx(
如何在C#中使用全局鼠标、键盘Hook            
int idHook,
如何在C#中使用全局鼠标、键盘Hook            HookProc lpfn,
如何在C#中使用全局鼠标、键盘Hook            IntPtr hMod,
如何在C#中使用全局鼠标、键盘Hook            
int dwThreadId);
如何在C#中使用全局鼠标、键盘Hook
如何在C#中使用全局鼠标、键盘Hook[DllImport(
"user32.dll", CharSet = CharSet.Auto,
如何在C#中使用全局鼠标、键盘Hook            CallingConvention 
= CallingConvention.StdCall, SetLastError = true)]
如何在C#中使用全局鼠标、键盘Hook        
private static extern int UnhookWindowsHookEx(int idHook);
如何在C#中使用全局鼠标、键盘Hook
如何在C#中使用全局鼠标、键盘Hook[DllImport(
"user32.dll", CharSet = CharSet.Auto,
如何在C#中使用全局鼠标、键盘Hook             CallingConvention 
= CallingConvention.StdCall)]
如何在C#中使用全局鼠标、键盘Hook        
private static extern int CallNextHookEx(
如何在C#中使用全局鼠标、键盘Hook            
int idHook,
如何在C#中使用全局鼠标、键盘Hook            
int nCode,
如何在C#中使用全局鼠标、键盘Hook            
int wParam,
如何在C#中使用全局鼠标、键盘Hook            IntPtr lParam);

  下面是有关这两个low-level hook在Winuser.h中的定义:

;

  在安装全局钩子的时候,我们就要做替换了,将WH_MOUSE和WH_KEYBORAD分别换成WH_MOUSE_LL和WH_KEYBORAD_LL:

如何在C#中使用全局鼠标、键盘Hook//install hook
如何在C#中使用全局鼠标、键盘Hook
                hMouseHook = SetWindowsHookEx(
如何在C#中使用全局鼠标、键盘Hook                    WH_MOUSE_LL, 
//原来是WH_MOUSE
如何在C#中使用全局鼠标、键盘Hook
                    MouseHookProcedure,
如何在C#中使用全局鼠标、键盘Hook                    Marshal.GetHINSTANCE(
如何在C#中使用全局鼠标、键盘Hook                        Assembly.GetExecutingAssembly().GetModules()[
0]),
如何在C#中使用全局鼠标、键盘Hook                    
0);
如何在C#中使用全局鼠标、键盘Hook
如何在C#中使用全局鼠标、键盘Hook
//install hook
如何在C#中使用全局鼠标、键盘Hook
                hKeyboardHook = SetWindowsHookEx(
如何在C#中使用全局鼠标、键盘Hook                    WH_KEYBOARD_LL, 
//原来是WH_KEYBORAD
如何在C#中使用全局鼠标、键盘Hook
                    KeyboardHookProcedure,
如何在C#中使用全局鼠标、键盘Hook                    Marshal.GetHINSTANCE(
如何在C#中使用全局鼠标、键盘Hook                    Assembly.GetExecutingAssembly().GetModules()[
0]),
如何在C#中使用全局鼠标、键盘Hook                    
0);
 
  这样替换了之后,我们就可以实现全局钩子了,而且,不需要写DLL。看一下程序运行情况:

如何在C#中使用全局鼠标、键盘Hook

  下面是关于鼠标和键盘的两个Callback函数:

如何在C#中使用全局鼠标、键盘Hookprivate int MouseHookProc(int nCode, int wParam, IntPtr lParam)

如何在C#中使用全局鼠标、键盘Hookprivate int KeyboardHookProc(int nCode, Int32 wParam, IntPtr lParam)
        }

  参考资料:MSDN

相关文章: