目前的程序中想要添加Hook,截获键盘按键消息,所以上网找了一下关于C#下Hook的东西。发现很多人都在说在C#中添加Hook不成功和不稳定,而建议使用C++封一个Dll给C#使用。,可喜的是最后我还是成功的在程序中使用C#添加了Hook,经过测试还是没有什么问题的。
进行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![None.gif](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
5
[DllImport(
"
user32.dll
"
)]
6
private
static
extern
int
UnhookWindowsHookEx(IntPtr hook);
7![None.gif](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
8
[DllImport(
"
user32.dll
"
)]
9
private
static
extern
int
CallNextHookEx(
10
IntPtr hook,
int
code, IntPtr wParam,
ref
KBDLLHOOKSTRUCT lParam);
![None.gif](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
2
![None.gif](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
3
![None.gif](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
4
![None.gif](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
5
![None.gif](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
6
![None.gif](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
7
![None.gif](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
8
![None.gif](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
9
![None.gif](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
10
![None.gif](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
我们需要定义一个delegate来接收消息
1
private
delegate
int
HookProc(
int
code, IntPtr wParam,
ref
KBDLLHOOKSTRUCT lParam);
![None.gif](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
定义两个event提供给外界使用
1
public
delegate
void
HookEventHandler(
object
sender, HookEventArgs e);
2
public
event
HookEventHandler KeyDown;
3
public
event
HookEventHandler KeyUp;
4
![None.gif](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
2
![None.gif](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
3
![None.gif](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
4
![None.gif](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
因为要接收的是键盘的消息所以要定义一些消息,和我们要接收的结构。
1
public
class
HookEventArgs : EventArgs
2![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
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![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
10
public HookEventArgs(UInt32 keyCode)
11![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
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
}
![None.gif](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
2
![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![ContractedBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
![dot.gif](https://www.cnblogs.com/Images/dot.gif)
3
![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
4
![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
5
![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
6
![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
7
![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
8
![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
9
![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
10
![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
11
![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
![dot.gif](https://www.cnblogs.com/Images/dot.gif)
12
![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
13
![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
14
![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
15
![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
16
![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
17
![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
18
![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
19
![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
20
![ExpandedSubBlockEnd.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
21
![ExpandedBlockEnd.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
1
private
enum
HookType :
int
2![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
3
WH_JOURNALRECORD = 0,
4
WH_JOURNALPLAYBACK = 1,
5
WH_KEYBOARD = 2,
6
WH_GETMESSAGE = 3,
7
WH_CALLWNDPROC = 4,
8
WH_CBT = 5,
9
WH_SYSMSGFILTER = 6,
10
WH_MOUSE = 7,
11
WH_HARDWARE = 8,
12
WH_DEBUG = 9,
13
WH_SHELL = 10,
14
WH_FOREGROUNDIDLE = 11,
15
WH_CALLWNDPROCRET = 12,
16
WH_KEYBOARD_LL = 13,
17
WH_MOUSE_LL = 14
18
}
19![None.gif](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
20
public
struct
KBDLLHOOKSTRUCT
21![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
22
public UInt32 vkCode;
23
public UInt32 scanCode;
24
public UInt32 flags;
25
public UInt32 time;
26
public IntPtr extraInfo;
27
}
![None.gif](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
2
![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![ContractedBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
![dot.gif](https://www.cnblogs.com/Images/dot.gif)
3
![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
4
![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
5
![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
6
![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
7
![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
8
![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
9
![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
10
![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
11
![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
12
![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
13
![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
14
![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
15
![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
16
![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
17
![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
18
![ExpandedBlockEnd.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
19
![None.gif](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
20
![None.gif](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
21
![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![ContractedBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
![dot.gif](https://www.cnblogs.com/Images/dot.gif)
22
![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
23
![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
24
![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
25
![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
26
![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
27
![ExpandedBlockEnd.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
关键的在这里 注册Hook
1
private
void
Install()
2![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
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![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
9
_hookHandle = SetWindowsHookEx(_hookType,
10
_hookFunction, Marshal.GetHINSTANCE(list[0]), 0);
11![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
12
}
哦,还有HookType _hookType = HookType.WH_KEYBOARD_LL; 因为要截获键盘消息
![None.gif](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
2
![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![ContractedBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
![dot.gif](https://www.cnblogs.com/Images/dot.gif)
3
![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
4
![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
5
![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
6
![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
7
![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
8
![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
9
![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
10
![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
11
![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
12
![ExpandedBlockEnd.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
还有_hookFunction = new HookProc(HookCallback);
其实最关键的是Marshal.GetHINSTANCE(list[0])得到当前程序的instance,这样这个Hook就是全局的Hook,这个位置也可以是null,这样就不是全局Hook。
有个很奇怪的现象就是这个函数,在调试状态执行不能成功,而做成Release以后运行成功,所以你在做程序时,不要因为调试失败而对这个函数有怀疑,编一个Release版本的程序,独立运行再试一下。我使用的环境是VS2005 + Vista。
接收消息的函数
1
private
int
HookCallback(
int
code, IntPtr wParam,
ref
KBDLLHOOKSTRUCT lParam)
2![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
3
if (code < 0)
4
return CallNextHookEx(_hookHandle, code, wParam, ref lParam);
5![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
6
if ((lParam.flags & 0x80) != 0 && this.KeyUp != null)
7
this.KeyUp(this, new HookEventArgs(lParam.vkCode));
8![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
9
if ((lParam.flags & 0x80) == 0 && this.KeyDown != null)
10![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
11
this.KeyDown(this, new HookEventArgs(lParam.vkCode));
12
if (lParam.vkCode == 44)
13![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
14
return 1;
15
}
16
}
17![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
18
return CallNextHookEx(_hookHandle, code, wParam, ref lParam);
19
}
这里会区分KeyUp和KeyDown,注意一定要调用CallNextHookEx,这样会将这个消息在系统中继续传递,这很重要。除非你想阻止这个消息,也不希望其他程序再处理这个消息。
![None.gif](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
2
![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![ContractedBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
![dot.gif](https://www.cnblogs.com/Images/dot.gif)
3
![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
4
![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
5
![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
6
![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
7
![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
8
![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
9
![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
10
![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
![dot.gif](https://www.cnblogs.com/Images/dot.gif)
11
![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
12
![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
13
![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
![dot.gif](https://www.cnblogs.com/Images/dot.gif)
14
![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
15
![ExpandedSubBlockEnd.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
16
![ExpandedSubBlockEnd.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
17
![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
18
![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
19
![ExpandedBlockEnd.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
下面最后的操作,释放注册。
1
private
void
Uninstall()
2![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
3
if (_hookHandle != IntPtr.Zero)
4![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
5
UnhookWindowsHookEx(_hookHandle);
6
_hookHandle = IntPtr.Zero;
7
}
8
}
![None.gif](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
2
![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![ContractedBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
![dot.gif](https://www.cnblogs.com/Images/dot.gif)
3
![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
4
![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
![dot.gif](https://www.cnblogs.com/Images/dot.gif)
5
![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
6
![InBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
7
![ExpandedSubBlockEnd.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
8
![ExpandedBlockEnd.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
Ok,完成了。