C#钩子实现简单鼠标键盘的监控和屏蔽

来源:互联网 发布:运维常用python脚本 编辑:程序博客网 时间:2024/05/01 05:20

概要

1 目的:完成简单的监控和屏蔽

2 技术:钩子(系统监控必须全局钩子)

3 步骤:

   A 安装钩子

   B 回调函数

   C 处理函数

   D 普通业务处理

   ……

4 完成

下载源程序和运行程序

http://files.cnblogs.com/hocylan/KeyboardHook.rar

 

说明:

C++中实现该功能十分简单,也有很多经典例子可以实现,在C#中确有很多问题会出现。

对于钩子知识不太熟悉可以参考我转载的另一篇文章:http://www.cnblogs.com/hocylan/articles/1033895.html[微软HOOK技术专题]

大概步骤

其实主要就是调用windows API
第一步
:安装钩子:SetWindowsHookEx(WH_Codes idHook, HookProc lpfn,IntPtr pInstance, int threadId);

第二步:回调和处理 CallNextHookEx(IntPtr pHookHandle, int nCode,Int32 wParam, IntPtr lParam);

第三步:完成普通的业务处理其它流程

        将封装的钩子应用到系统中…….

        private void start_Click(object sender, EventArgs e)

        { hook_Main.InstallHook("1");}

        private void stop_Click(object sender, EventArgs e)

        {this.hook_Main.UnInstallHook();}

        private void stopkeyboard_Click(object sender, EventArgs e)

        { hook_Main.InstallHook("2"); }

第四步:拆卸钩子UnhookWindowsHookEx(IntPtr pHookHandle);

 

四 重要代码和解释:

*封装的hook类:

  1. using System;
  2. using System.Windows.Forms;
  3. using System.Runtime.InteropServices; //必须引用
  4. using System.Reflection; //必须引用
  5. namespace KeyboardHook
  6. {
  7.     public class Hocy_Hook
  8.     {
  9.         #region 私有常量
  10.         ///<summary>
  11.         ///按键状态数组
  12.         ///</summary>
  13.         private readonly byte[] m_KeyState = new byte[256];
  14.         private string flags;
  15.         //flag=0 正常 flag=1 监控状态 flag=2 屏蔽键盘//
  16.         #endregion 私有常量
  17.         #region 私有变量
  18.         ///<summary>
  19.         ///鼠标钩子句柄
  20.         ///</summary>
  21.         private IntPtr m_pMouseHook = IntPtr.Zero;
  22.         ///<summary>
  23.         ///键盘钩子句柄
  24.         ///</summary>
  25.         private IntPtr m_pKeyboardHook = IntPtr.Zero;
  26.         ///<summary>
  27.         ///鼠标钩子委托实例
  28.         ///</summary>
  29.         ///<remarks>
  30.         ///不要试图省略此变量,否则将会导致
  31.         ///激活CallbackOnCollectedDelegate 托管调试助手(MDA)。
  32.         ///详细请参见MSDN中关于CallbackOnCollectedDelegate 的描述
  33.         ///</remarks>
  34.         private HookProc m_MouseHookProcedure;
  35.         ///<summary>
  36.         ///键盘钩子委托实例
  37.         ///</summary>
  38.         ///<remarks>
  39.         ///不要试图省略此变量,否则将会导致
  40.         ///激活CallbackOnCollectedDelegate 托管调试助手(MDA)。
  41.         ///详细请参见MSDN中关于CallbackOnCollectedDelegate 的描述
  42.         ///</remarks>
  43.         private HookProc m_KeyboardHookProcedure;
  44.         // 添加
  45.         public event MouseEventHandler OnMouseActivity;
  46.         private const byte VK_SHIFT = 0x10;
  47.         private const byte VK_CAPITAL = 0x14;
  48.         private const byte VK_NUMLOCK = 0x90;
  49.         #endregion 私有变量
  50.         #region 事件定义
  51.         ///<summary>
  52.         ///鼠标更新事件
  53.         ///</summary>
  54.         ///<remarks>当鼠标移动或者滚轮滚动时触发</remarks>
  55.         public event MouseUpdateEventHandler OnMouseUpdate;
  56.         ///<summary>
  57.         ///按键按下事件
  58.         ///</summary>
  59.         public event KeyEventHandler OnKeyDown;
  60.         ///<summary>
  61.         ///按键按下并释放事件
  62.         ///</summary>
  63.         public event KeyPressEventHandler OnKeyPress;
  64.         ///<summary>
  65.         ///按键释放事件
  66.         ///</summary>
  67.         public event KeyEventHandler OnKeyUp;
  68.         #endregion 事件定义
  69.         #region 私有方法
  70.         ///<summary>
  71.         ///鼠标钩子处理函数
  72.         ///</summary>
  73.         ///<param name="nCode"></param>
  74.         ///<param name="wParam"></param>
  75.         ///<param name="lParam"></param>
  76.         ///<returns>鼠标钩子处理函数</returns>
  77.         private int MouseHookProc( int nCode, Int32 wParam, IntPtr lParam )
  78.         {
  79.             if ( ( nCode >= 0 ) && ( OnMouseActivity != null ) )
  80.             {
  81.                 //Marshall the data from callback.
  82.                 MouseHookStruct mouseHookStruct = ( MouseHookStruct )Marshal.PtrToStructure( lParam, typeof( MouseHookStruct ) );
  83.                 //detect button clicked
  84.                 MouseButtons button = MouseButtons.None;
  85.                 short mouseDelta = 0;
  86.                 switch ( wParam )
  87.                 {
  88.                     case ( int )WM_MOUSE.WM_LBUTTONDOWN:
  89.                         //case WM_LBUTTONUP: 
  90.                         //case WM_LBUTTONDBLCLK: 
  91.                         button = MouseButtons.Left;
  92.                         break;
  93.                     case ( int )WM_MOUSE.WM_RBUTTONDOWN:
  94.                         //case WM_RBUTTONUP: 
  95.                         //case WM_RBUTTONDBLCLK: 
  96.                         button = MouseButtons.Right;
  97.                         break;
  98.                     case ( int )WM_MOUSE.WM_MOUSEWHEEL:
  99.                         //If the message is WM_MOUSEWHEEL, the high-order word of mouseData member is the wheel delta. 
  100.                         //One wheel click is defined as WHEEL_DELTA, which is 120. 
  101.                         //(value >> 16) & 0xffff; retrieves the high-order word from the given 32-bit value
  102.                         mouseDelta = ( short )( ( mouseHookStruct.MouseData >> 16 ) & 0xffff );
  103.                         //TODO: X BUTTONS (I havent them so was unable to test)
  104.                         //If the message is WM_XBUTTONDOWN, WM_XBUTTONUP, WM_XBUTTONDBLCLK, WM_NCXBUTTONDOWN, WM_NCXBUTTONUP, 
  105.                         //or WM_NCXBUTTONDBLCLK, the high-order word specifies which X button was pressed or released, 
  106.                         //and the low-order word is reserved. This value can be one or more of the following values. 
  107.                         //Otherwise, mouseData is not used. 
  108.                         break;
  109.                 }
  110.                 //double clicks
  111.                 int clickCount = 0;
  112.                 if ( button != MouseButtons.None )
  113.                     if ( wParam == ( int )WM_MOUSE.WM_LBUTTONDBLCLK || wParam == ( int )WM_MOUSE.WM_RBUTTONDBLCLK ) clickCount = 2;
  114.                     else clickCount = 1;
  115.                 //generate event 
  116.                 MouseEventArgs e = new MouseEventArgs(
  117.                                                    button,
  118.                                                    clickCount,
  119.                                                    mouseHookStruct.Point.X,
  120.                                                    mouseHookStruct.Point.Y,
  121.                                                    mouseDelta );
  122.                 //raise it
  123.                 OnMouseActivity( this, e );
  124.             }
  125.             //*
  126.             return Win32API.CallNextHookEx( this.m_pMouseHook, nCode, wParam, lParam );
  127.         }
  128.         ///<summary>
  129.         ///键盘钩子处理函数
  130.         ///</summary>
  131.         ///<param name="nCode"></param>
  132.         ///<param name="wParam"></param>
  133.         ///<param name="lParam"></param>
  134.         ///<returns></returns>
  135.         ///<remarks></remarks>
  136.         private int KeyboardHookProc( int nCode, Int32 wParam, IntPtr lParam )
  137.         {
  138.             switch ( flags )
  139.             {
  140.                 case "2":
  141.                     return 1;
  142.                     break;
  143.                 case "1":
  144.                     break;
  145.             }
  146.             bool handled = false;
  147.             //it was ok and someone listens to events
  148.             if ( ( nCode >= 0 ) && ( this.OnKeyDown != null || this.OnKeyUp != null || this.OnKeyPress != null ) )
  149.             {
  150.                 //read structure KeyboardHookStruct at lParam
  151.                 KeyboardHookStruct MyKeyboardHookStruct = ( KeyboardHookStruct )Marshal.PtrToStructure( lParam, typeof( KeyboardHookStruct ) );
  152.                 //raise KeyDown
  153.                 if ( this.OnKeyDown != null && ( wParam == ( int )WM_KEYBOARD.WM_KEYDOWN || wParam == ( int )WM_KEYBOARD.WM_SYSKEYDOWN ) )
  154.                 {
  155.                     Keys keyData = ( Keys )MyKeyboardHookStruct.VKCode;
  156.                     KeyEventArgs e = new KeyEventArgs( keyData );
  157.                     this.OnKeyDown( this, e );
  158.                     handled = handled || e.Handled;
  159.                 }
  160.                 // raise KeyPress
  161.                 if ( this.OnKeyPress != null && wParam == ( int )WM_KEYBOARD.WM_KEYDOWN )
  162.                 {
  163.                     bool isDownShift, isDownCapslock;
  164.                     try
  165.                     {
  166.                         isDownShift = ( ( Win32API.GetKeyStates( VK_SHIFT ) & 0x80 ) == 0x80 ? true : false );
  167.                         isDownCapslock = ( Win32API.GetKeyStates( VK_CAPITAL ) != 0 ? true : false );
  168.                     }
  169.                     catch
  170.                     {
  171.                         isDownCapslock = false;
  172.                         isDownShift = false;
  173.                     }
  174.                     byte[] keyState = new byte[256];
  175.                     Win32API.GetKeyboardState( keyState );
  176.                     byte[] inBuffer = new byte[2];
  177.                     if ( Win32API.ToAscii( MyKeyboardHookStruct.VKCode,
  178.                               MyKeyboardHookStruct.ScanCode,
  179.                               keyState,
  180.                               inBuffer,
  181.                               MyKeyboardHookStruct.Flags ) == 1 )
  182.                     {
  183.                         char key = ( char )inBuffer[0];
  184.                         if ( ( isDownCapslock ^ isDownShift ) && Char.IsLetter( key ) ) key = Char.ToUpper( key );
  185.                         KeyPressEventArgs e = new KeyPressEventArgs( key );
  186.                         this.OnKeyPress( this, e );
  187.                         handled = handled || e.Handled;
  188.                     }
  189.                 }
  190.                 // raise KeyUp
  191.                 if ( this.OnKeyUp != null && ( wParam == ( int )WM_KEYBOARD.WM_KEYUP || wParam == ( int )WM_KEYBOARD.WM_SYSKEYUP ) )
  192.                 {
  193.                     Keys keyData = ( Keys )MyKeyboardHookStruct.VKCode;
  194.                     KeyEventArgs e = new KeyEventArgs( keyData );
  195.                     this.OnKeyUp( this, e );
  196.                     handled = handled || e.Handled;
  197.                 }
  198.             }
  199.             //if event handled in application do not handoff to other listeners
  200.             if ( handled )
  201.                 return 1;
  202.             else
  203.                 return Win32API.CallNextHookEx( this.m_pKeyboardHook, nCode, wParam, lParam );
  204.         }
  205.         #endregion 私有方法
  206.         #region 公共方法
  207.         ///<summary>
  208.         ///安装钩子
  209.         ///</summary>
  210.         ///<returns></returns>
  211.         public bool InstallHook( string flagsinfo )
  212.         {
  213.             this.flags = flagsinfo;
  214.             IntPtr pInstance = Marshal.GetHINSTANCE( Assembly.GetExecutingAssembly().ManifestModule );
  215.             //pInstance = (IntPtr)4194304;
  216.             //注意:很多时候得到的pInstanc无法安装钩子,请检查值是否为4194304,在应用程序中可以直接取得pinstance的
  217.             // IntPtr pInstanc2 = Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly());
  218.             // Assembly.GetExecutingAssembly().GetModules()[0]
  219.             //安装鼠标钩子
  220.             if ( this.m_pMouseHook == IntPtr.Zero )
  221.             {
  222.                 this.m_MouseHookProcedure = new HookProc( this.MouseHookProc );
  223.                 this.m_pMouseHook = Win32API.SetWindowsHookEx( WH_Codes.WH_MOUSE_LL, this.m_MouseHookProcedure, pInstance, 0 );
  224.                 // WH_Codes.WH_MOUSE_LL为全局钩子即系统钩子,否则应该为WH_Codes.WH_KEYBOARD,即普通钩子
  225.                 if ( this.m_pMouseHook == IntPtr.Zero )
  226.                 {
  227.                     this.UnInstallHook();
  228.                     return false;
  229.                 }
  230.             }
  231.             if ( this.m_pKeyboardHook == IntPtr.Zero ) //安装键盘钩子
  232.             {
  233.                 this.m_KeyboardHookProcedure = new HookProc( this.KeyboardHookProc );
  234.                 // WH_Codes.WH_KEYBOARD_LL为全局钩子即系统钩子,否则应该为WH_Codes.WH_KEYBOARD,即普通钩子
  235.                 this.m_pKeyboardHook = Win32API.SetWindowsHookEx( WH_Codes.WH_KEYBOARD_LL, this.m_KeyboardHookProcedure, pInstance, 0 );
  236.                 if ( this.m_pKeyboardHook == IntPtr.Zero )
  237.                 {
  238.                     this.UnInstallHook();
  239.                     return false;
  240.                 }
  241.             }
  242.             return true;
  243.         }
  244.         ///<summary>
  245.         ///卸载钩子
  246.         ///</summary>
  247.         ///<returns></returns>
  248.         public bool UnInstallHook()
  249.         {
  250.             bool result = true;
  251.             if ( this.m_pMouseHook != IntPtr.Zero )
  252.             {
  253.                 result = ( Win32API.UnhookWindowsHookEx( this.m_pMouseHook ) && result );
  254.                 this.m_pMouseHook = IntPtr.Zero;
  255.             }
  256.             if ( this.m_pKeyboardHook != IntPtr.Zero )
  257.             {
  258.                 result = ( Win32API.UnhookWindowsHookEx( this.m_pKeyboardHook ) && result );
  259.                 this.m_pKeyboardHook = IntPtr.Zero;
  260.             }
  261.             return result;
  262.         }
  263.         #endregion 公共方法
  264.         #region 构造函数
  265.         ///<summary>
  266.         ///钩子类
  267.         ///</summary>
  268.         ///<remarks>本类仅仅简单实现了WH_KEYBOARD_LL 以及WH_MOUSE_LL </remarks>
  269.         public Hocy_Hook()
  270.         {
  271.             Win32API.GetKeyboardState( this.m_KeyState );
  272.         }
  273.         #endregion 构造函数
  274.     }
  275. }
原创粉丝点击