C#钩子学习笔记
什么是钩子
Windows操作系统为我们提供了许多钩子(Hooks),如键盘钩子、鼠标钩子、Windows消息钩子、时间戳钩子等。钩子可以让我们在系统层面对各种事件消息进行拦截、监控、修改或者定制化输出等操作。
钩子的分类
Windows中的钩子有很多种,我们可以将它们大体分为两类:
- 系统钩子 (system-wide hook):作用于整个系统,能够接收到所有相关事件消息。
- 应用程序钩子 (application-specific hook):只作用于当前应用程序,只能接收到当前应用程序相关的事件消息。
钩子的实现
我们可以使用C#代码来实现钩子,具体步骤如下:
- 定义一个回调函数来处理钩子事件,回调函数必须为标准的回调委托类型。
- 通过调用Win32 API的SetWindowsHookEx函数来注册钩子,获取钩子句柄。
- 使用Win32 API的UnhookWindowsHookEx函数来卸载钩子,及时释放系统资源。
示例1:键盘钩子
以下是一个基于C#和Win32 API的系统键盘钩子实现。
using System;
using System.Runtime.InteropServices;
namespace KeyboardHookDemo {
class Program {
//定义回调委托
private delegate IntPtr HookDelegate(int nCode, IntPtr wParam, IntPtr lParam);
//定义键盘输入事件枚举
private enum KeyboardMsg {
WmKeyDown = 0x0100,
WmKeyUp = 0x0101
}
//定义键盘状态检查枚举
private enum KeyboardState {
KeyDown = 0x8000,
AltKeyPressed = 0x2000,
CtrlKeyPressed = 0x0008,
ShiftKeyPressed = 0x0100
}
//定义钩子事件回调函数
private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam) {
//判断是否为键盘输入事件
if (nCode < 0 || (int)wParam != (int)KeyboardMsg.WmKeyDown) {
//传递给下一个钩子
return CallNextHookEx(hookId, nCode, wParam, lParam);
}
//获取键盘事件的基本信息
int vkCode = Marshal.ReadInt32(lParam);
bool isAltKeyPress = ((GetKeyState((int)KeyboardState.AltKeyPressed) & KeyboardState.AltKeyPressed) != 0);
bool isCtrlKeyPress = ((GetKeyState((int)KeyboardState.CtrlKeyPressed) & KeyboardState.CtrlKeyPressed) != 0);
bool isShiftKeyPress = ((GetKeyState((int)KeyboardState.ShiftKeyPressed) & KeyboardState.ShiftKeyPressed) != 0);
//输出按键信息
Console.WriteLine(string.Format("{0} {1} {2} {3}", isAltKeyPress, isCtrlKeyPress, isShiftKeyPress, (Keys)vkCode));
//传递给下一个钩子
return CallNextHookEx(hookId, nCode, wParam, lParam);
}
//导入Windows API函数
[DllImport("user32.dll")]
private static extern IntPtr SetWindowsHookEx(int idHook, HookDelegate lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll")]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll")]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll")]
private static extern short GetKeyState(int nVirtKey);
[DllImport("kernel32.dll")]
private static extern IntPtr GetModuleHandle(string lpModuleName);
//定义钩子ID
private static IntPtr hookId = IntPtr.Zero;
static void Main(string[] args) {
//注册钩子
hookId = SetWindowsHookEx((int)13, new HookDelegate(HookCallback), GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName), 0);
//等待程序退出
Application.Run();
//卸载钩子
UnhookWindowsHookEx(hookId);
}
}
}
示例2:鼠标钩子
以下是一个基于C#和Win32 API的应用程序鼠标钩子实现。
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace MouseHookDemo {
class Program {
//定义回调委托
private delegate IntPtr HookDelegate(int nCode, IntPtr wParam, IntPtr lParam);
//定义鼠标输入事件枚举
private enum MouseMsg {
WmMouseMove = 0x200,
WmLButtonDown = 0x201,
WmLButtonUp = 0x202,
WmRButtonDown = 0x204,
WmRButtonUp = 0x205,
WmMButtonDown = 0x207,
WmMButtonUp = 0x208,
WmMouseWheel = 0x20A
}
//定义鼠标状态检查枚举
private enum MouseState {
LeftButtonPressed = 0x0001,
RightButtonPressed = 0x0002,
MiddleButtonPressed = 0x0010,
AltKeyPressed = 0x0002,
CtrlKeyPressed = 0x0008,
ShiftKeyPressed = 0x0100
}
//定义钩子事件回调函数
private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam) {
//判断是否为鼠标输入事件
if (nCode < 0 || wParam == IntPtr.Zero) {
//传递给下一个钩子
return CallNextHookEx(hookId, nCode, wParam, lParam);
}
//获取鼠标事件的基本信息
MouseMsg msg = (MouseMsg)wParam;
Point pt = new Point();
GetCursorPos(out pt);
short wheelDelta = (short)0;
if (msg == MouseMsg.WmMouseWheel) {
wheelDelta = (short)HIWORD((uint)lParam);
}
bool isCtrlKeyPress = ((GetKeyState((int)MouseState.CtrlKeyPressed) & MouseState.CtrlKeyPressed) != 0);
bool isShiftKeyPress = ((GetKeyState((int)MouseState.ShiftKeyPressed) & MouseState.ShiftKeyPressed) != 0);
bool isAltKeyPress = ((GetKeyState((int)MouseState.AltKeyPressed) & MouseState.AltKeyPressed) != 0);
bool isLeftButtonPressed = ((GetKeyState((int)MouseState.LeftButtonPressed) & MouseState.LeftButtonPressed) != 0);
bool isRightButtonPressed = ((GetKeyState((int)MouseState.RightButtonPressed) & MouseState.RightButtonPressed) != 0);
bool isMiddleButtonPressed = ((GetKeyState((int)MouseState.MiddleButtonPressed) & MouseState.MiddleButtonPressed) != 0);
//输出鼠标事件信息
Console.WriteLine(string.Format("{0} {1} {2} {3} {4} {5} {6} ({7},{8}) {9}", isAltKeyPress, isCtrlKeyPress, isShiftKeyPress, isLeftButtonPressed, isRightButtonPressed, isMiddleButtonPressed, wheelDelta, pt.X, pt.Y, msg));
//传递给下一个钩子
return CallNextHookEx(hookId, nCode, wParam, lParam);
}
//导入Windows API函数
[DllImport("user32.dll")]
private static extern IntPtr SetWindowsHookEx(int idHook, HookDelegate lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll")]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll")]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll")]
private static extern short GetKeyState(int nVirtKey);
[DllImport("user32.dll")]
private static extern bool GetCursorPos(out Point lpPoint);
[DllImport("user32.dll")]
private static extern uint GetMessagePos();
private static int HIWORD(uint dword) {
return (int)(short)(dword >> 16);
}
//定义钩子ID
private static IntPtr hookId = IntPtr.Zero;
static void Main(string[] args) {
//注册钩子
hookId = SetWindowsHookEx((int)14, new HookDelegate(HookCallback), GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName), 0);
//等待程序退出
Application.Run();
//卸载钩子
UnhookWindowsHookEx(hookId);
}
}
}
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:c# 钩子学习笔记 - Python技术站