C#中实现Hook

目前的程序中想要添加Hook,截获键盘按键消息,所以上网找了一下关于C#下Hook的东西。发现很多人都在说在C#中添加Hook不成功和不稳定,而建议使用C++封一个Dll给C#使用。smile.gif,可喜的是最后我还是成功的在程序中使用C#添加了Hook,经过测试还是没有什么问题的。
进行Hook需要使用三个API函数
SetWindowsHookEx  进行Hook的注册
UnhookWindowsHookEx  取消已经注册的Hook
CallNextHookEx  将消息传递给下一个Hook函数

看一下定义

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

我们需要定义一个delegate来接收消息
1 None.gif          private   delegate   int  HookProc( int  code, IntPtr wParam,  ref  KBDLLHOOKSTRUCT lParam);

定义两个event提供给外界使用
1 None.gif          public   delegate   void  HookEventHandler( object  sender, HookEventArgs e);
2 None.gif         public   event  HookEventHandler KeyDown;
3 None.gif         public   event  HookEventHandler KeyUp;
4 None.gif

因为要接收的是键盘的消息所以要定义一些消息,和我们要接收的结构。
 1 None.gif      public   class  HookEventArgs : EventArgs
 2 ExpandedBlockStart.gifContractedBlock.gif     dot.gif {
 3InBlock.gif        // using Windows.Forms.Keys instead of Input.Key since the Forms.Keys maps
 4InBlock.gif        // to the Win32 KBDLLHOOKSTRUCT virtual key member, where Input.Key does not
 5InBlock.gif        public Keys Key;
 6InBlock.gif        public bool Alt;
 7InBlock.gif        public bool Control;
 8InBlock.gif        public bool Shift;
 9InBlock.gif
10InBlock.gif        public HookEventArgs(UInt32 keyCode)
11ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
12InBlock.gif            // detect what modifier keys are pressed, using 
13InBlock.gif            // Windows.Forms.Control.ModifierKeys instead of Keyboard.Modifiers
14InBlock.gif            // since Keyboard.Modifiers does not correctly get the state of the 
15InBlock.gif            // modifier keys when the application does not have focus
16InBlock.gif            this.Key = (Keys)keyCode;
17InBlock.gif            this.Alt = (System.Windows.Forms.Control.ModifierKeys & Keys.Alt) != 0;
18InBlock.gif            this.Control = (System.Windows.Forms.Control.ModifierKeys & Keys.Control) != 0;
19InBlock.gif            this.Shift = (System.Windows.Forms.Control.ModifierKeys & Keys.Shift) != 0;
20ExpandedSubBlockEnd.gif        }

21ExpandedBlockEnd.gif    }

 1 None.gif        private   enum  HookType :  int
 2 ExpandedBlockStart.gifContractedBlock.gif         dot.gif {
 3InBlock.gif            WH_JOURNALRECORD = 0,
 4InBlock.gif            WH_JOURNALPLAYBACK = 1,
 5InBlock.gif            WH_KEYBOARD = 2,
 6InBlock.gif            WH_GETMESSAGE = 3,
 7InBlock.gif            WH_CALLWNDPROC = 4,
 8InBlock.gif            WH_CBT = 5,
 9InBlock.gif            WH_SYSMSGFILTER = 6,
10InBlock.gif            WH_MOUSE = 7,
11InBlock.gif            WH_HARDWARE = 8,
12InBlock.gif            WH_DEBUG = 9,
13InBlock.gif            WH_SHELL = 10,
14InBlock.gif            WH_FOREGROUNDIDLE = 11,
15InBlock.gif            WH_CALLWNDPROCRET = 12,
16InBlock.gif            WH_KEYBOARD_LL = 13,
17InBlock.gif            WH_MOUSE_LL = 14
18ExpandedBlockEnd.gif        }

19 None.gif
20 None.gif         public   struct  KBDLLHOOKSTRUCT
21 ExpandedBlockStart.gifContractedBlock.gif         dot.gif {
22InBlock.gif            public UInt32 vkCode;
23InBlock.gif            public UInt32 scanCode;
24InBlock.gif            public UInt32 flags;
25InBlock.gif            public UInt32 time;
26InBlock.gif            public IntPtr extraInfo;
27ExpandedBlockEnd.gif        }

关键的在这里 注册Hook
 1 None.gif          private   void  Install()
 2 ExpandedBlockStart.gifContractedBlock.gif         dot.gif {
 3InBlock.gif            if (_hookHandle != IntPtr.Zero)
 4InBlock.gif                return;
 5InBlock.gif                
 6InBlock.gif            Module[] list = System.Reflection.Assembly.GetExecutingAssembly().GetModules();
 7InBlock.gif            System.Diagnostics.Debug.Assert(list != null && list.Length > 0);
 8InBlock.gif
 9InBlock.gif            _hookHandle = SetWindowsHookEx(_hookType, 
10InBlock.gif                _hookFunction, Marshal.GetHINSTANCE(list[0]), 0);
11InBlock.gif
12ExpandedBlockEnd.gif        }
哦,还有HookType _hookType = HookType.WH_KEYBOARD_LL; 因为要截获键盘消息
还有_hookFunction = new HookProc(HookCallback);
其实最关键的是Marshal.GetHINSTANCE(list[0])得到当前程序的instance,这样这个Hook就是全局的Hook,这个位置也可以是null,这样就不是全局Hook。
有个很奇怪的现象就是这个函数,在调试状态执行不能成功,而做成Release以后运行成功,所以你在做程序时,不要因为调试失败而对这个函数有怀疑,编一个Release版本的程序,独立运行再试一下。我使用的环境是VS2005 + Vista。

接收消息的函数
 1 None.gif          private   int  HookCallback( int  code, IntPtr wParam,  ref  KBDLLHOOKSTRUCT lParam)
 2 ExpandedBlockStart.gifContractedBlock.gif         dot.gif {
 3InBlock.gif            if (code < 0)
 4InBlock.gif                return CallNextHookEx(_hookHandle, code, wParam, ref lParam);
 5InBlock.gif
 6InBlock.gif            if ((lParam.flags & 0x80!= 0 && this.KeyUp != null)
 7InBlock.gif                this.KeyUp(thisnew HookEventArgs(lParam.vkCode));
 8InBlock.gif
 9InBlock.gif            if ((lParam.flags & 0x80== 0 && this.KeyDown != null)
10ExpandedSubBlockStart.gifContractedSubBlock.gif            dot.gif{
11InBlock.gif                this.KeyDown(thisnew HookEventArgs(lParam.vkCode));
12InBlock.gif                if (lParam.vkCode == 44)
13ExpandedSubBlockStart.gifContractedSubBlock.gif                dot.gif{
14InBlock.gif                    return 1;
15ExpandedSubBlockEnd.gif                }

16ExpandedSubBlockEnd.gif            }

17InBlock.gif
18InBlock.gif            return CallNextHookEx(_hookHandle, code, wParam, ref lParam);
19ExpandedBlockEnd.gif        }
这里会区分KeyUp和KeyDown,注意一定要调用CallNextHookEx,这样会将这个消息在系统中继续传递,这很重要。除非你想阻止这个消息,也不希望其他程序再处理这个消息。

下面最后的操作,释放注册。
1 None.gif          private   void  Uninstall()
2 ExpandedBlockStart.gifContractedBlock.gif         dot.gif {
3InBlock.gif            if (_hookHandle != IntPtr.Zero)
4ExpandedSubBlockStart.gifContractedSubBlock.gif            dot.gif{
5InBlock.gif                UnhookWindowsHookEx(_hookHandle);
6InBlock.gif                _hookHandle = IntPtr.Zero;
7ExpandedSubBlockEnd.gif            }

8ExpandedBlockEnd.gif        }

Ok,完成了。

转载于:https://www.cnblogs.com/dougua/archive/2007/07/05/806465.html

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值