看看C#Hook如何实现

目前的程序中想要添加Hook,截获键盘按键消息,所以上网找了一下关于C# Hook的东西。发现很多人都在说在添加C# Hook不成功和不稳定,而建议使用C++封一个Dll给C#使用。可喜的是最后我还是成功的在程序中使用C#添加了Hook,经过测试还是没有什么问题的。

创新互联建站专业为企业提供邯山网站建设、邯山做网站、邯山网站设计、邯山网站制作等企业网站建设、网页设计与制作、邯山企业网站模板建站服务,10年邯山做网站经验,不只是建网站,更提供有价值的思路和整体网络服务。

进行Hook需要使用三个API函数

SetWindowsHookEx 进行Hook的注册

UnhookWindowsHookEx 取消已经注册的Hook

CallNextHookEx 将消息传递给下一个Hook函数

看一下定义

 
 
 
  1. [DllImport("user32.dll")]  
  2. private static extern IntPtr SetWindowsHookEx(  
  3.     HookType code, HookProc func, IntPtr instance, int threadID);  
  4.  
  5. [DllImport("user32.dll")]  
  6. private static extern int UnhookWindowsHookEx(IntPtr hook);  
  7.  
  8. [DllImport("user32.dll")]  
  9. private static extern int CallNextHookEx(  
  10.     IntPtr hook, int code, IntPtr wParam, ref KBDLLHOOKSTRUCT lParam); 

我们需要定义一个delegate来接收消息

 
 
 
  1. private delegate int HookProc(int code, IntPtr wParam, ref KBDLLHOOKSTRUCT lParam); 

定义两个event提供给外界使用

 
 
 
  1. public delegate void HookEventHandler(object sender, HookEventArgs e);  
  2. public event HookEventHandler KeyDown;  
  3. public event HookEventHandler KeyUp; 

因为要接收的是键盘的消息所以要定义一些消息,和我们要接收的结构。 

 
 
 
  1. public class HookEventArgs : EventArgs  
  2.  {  
  3.      // using Windows.Forms.Keys instead of Input.Key since the Forms.Keys maps  
  4.      // to the Win32 KBDLLHOOKSTRUCT virtual key member, where Input.Key does not  
  5.      public Keys Key;  
  6.      public bool Alt;  
  7.      public bool Control;  
  8.      public bool Shift;  
  9.  
  10.      public HookEventArgs(UInt32 keyCode)  
  11.      {  
  12.          // detect what modifier keys are pressed, using   
  13.          // Windows.Forms.Control.ModifierKeys instead of Keyboard.Modifiers  
  14.          // since Keyboard.Modifiers does not correctly get the state of the   
  15.          // modifier keys when the application does not have focus  
  16.          this.Key = (Keys)keyCode;  
  17.          this.Alt = (System.Windows.Forms.Control.ModifierKeys & Keys.Alt) != 0;  
  18.          this.Control = (System.Windows.Forms.Control.ModifierKeys & Keys.Control) != 0;  
  19.          this.Shift = (System.Windows.Forms.Control.ModifierKeys & Keys.Shift) != 0;  
  20.      }  
  21.  }  
  22.  
  23.      private enum HookType : int 
  24.     {  
  25.         WH_JOURNALRECORD = 0,  
  26.         WH_JOURNALPLAYBACK = 1,  
  27.         WH_KEYBOARD = 2,  
  28.         WH_GETMESSAGE = 3,  
  29.         WH_CALLWNDPROC = 4,  
  30.         WH_CBT = 5,  
  31.         WH_SYSMSGFILTER = 6,  
  32.          WH_MOUSE = 7,  
  33.          WH_HARDWARE = 8,  
  34.          WH_DEBUG = 9,  
  35.          WH_SHELL = 10,  
  36.          WH_FOREGROUNDIDLE = 11,  
  37.          WH_CALLWNDPROCRET = 12,  
  38.          WH_KEYBOARD_LL = 13,  
  39.          WH_MOUSE_LL = 14  
  40.      }  
  41.  
  42.      public struct KBDLLHOOKSTRUCT  
  43.      {  
  44.          public UInt32 vkCode;  
  45.          public UInt32 scanCode;  
  46.          public UInt32 flags;  
  47.          public UInt32 time;  
  48.          public IntPtr extraInfo;  
  49.      } 

关键的在这里注册C# Hook 

 
 
 
  1. private void Install()  
  2.  {  
  3.      if (_hookHandle != IntPtr.Zero)  
  4.          return;  
  5.            
  6.      Module[] list = System.Reflection.Assembly.GetExecutingAssembly().GetModules();  
  7.      System.Diagnostics.Debug.Assert(list != null && list.Length > 0);  
  8.  
  9.     _hookHandle = SetWindowsHookEx(_hookType,   
  10.          _hookFunction, Marshal.GetHINSTANCE(list[0]), 0);  
  11.  
  12.  } 

哦,还有HookType _hookType = HookType.WH_KEYBOARD_LL; 因为要截获键盘消息

还有_hookFunction = new HookProc(HookCallback);

其实最关键的是Marshal.GetHINSTANCE(list[0])得到当前程序的instance,这样这个C# Hook就是全局的C# Hook,这个位置也可以是null,这样就不是全局C# Hook。

有个很奇怪的现象就是这个函数,在调试状态执行不能成功,而做成Release以后运行成功,所以你在做程序时,不要因为调试失败而对这个函数有怀疑,编一个Release版本的程序,独立运行再试一下。我使用的环境是VS2005 + Vista。

接收消息的函数 

 
 
 
  1. private int HookCallback(int code, IntPtr wParam, ref KBDLLHOOKSTRUCT lParam)  
  2.  {  
  3.      if (code <  0)  
  4.          return CallNextHookEx(_hookHandle, code, wParam, ref lParam);  
  5.  
  6.      if ((lParam.flags & 0x80) != 0 && this.KeyUp != null)  
  7.          this.KeyUp(this, new HookEventArgs(lParam.vkCode));  
  8.  
  9.      if ((lParam.flags & 0x80) == 0 && this.KeyDown != null)  
  10.      {  
  11.          this.KeyDown(this, new HookEventArgs(lParam.vkCode));  
  12.          if (lParam.vkCode == 44)  
  13.          {  
  14.              return 1;  
  15.          }  
  16.      }  
  17.  
  18.      return CallNextHookEx(_hookHandle, code, wParam, ref lParam);  
  19.  } 

这里会区分KeyUp和KeyDown,注意一定要调用CallNextHookEx,这样会将这个消息在系统中继续传递,这很重要。除非你想阻止这个消息,也不希望其他程序再处理这个消息。

下面最后的操作,释放注册。

 
 
 
  1. private void Uninstall()  
  2. {  
  3.     if (_hookHandle != IntPtr.Zero)  
  4.     {  
  5.         UnhookWindowsHookEx(_hookHandle);  
  6.         _hookHandle = IntPtr.Zero;  
  7.     }  

Ok,完成了。

网页名称:看看C#Hook如何实现
网页链接:http://www.shufengxianlan.com/qtweb/news21/141571.html

网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联