消息钩子函数入门篇.docx
5分钟掌握Python中的Hook钩子函数

5分钟掌握Python中的Hook钩子函数1. 什么是Hook经常会听到钩子函数(hook function)这个概念,最近在看目标检测开源框架mmdetection,里面也出现大量Hook的编程方式,那到底什么是hook?hook的作用是什么?•what is hook ?钩子hook,顾名思义,可以理解是一个挂钩,作用是有需要的时候挂一个东西上去。
具体的解释是:钩子函数是把我们自己实现的hook函数在某一时刻挂接到目标挂载点上。
•hook函数的作用举个例子,hook的概念在windows桌面软件开发很常见,特别是各种事件触发的机制; 比如C++的MFC程序中,要监听鼠标左键按下的时间,MFC提供了一个onLeftKeyDown的钩子函数。
很显然,MFC框架并没有为我们实现onLeftKeyDown具体的操作,只是为我们提供一个钩子,当我们需要处理的时候,只要去重写这个函数,把我们需要操作挂载在这个钩子里,如果我们不挂载,MFC事件触发机制中执行的就是空的操作。
从上面可知•hook函数是程序中预定义好的函数,这个函数处于原有程序流程当中(暴露一个钩子出来)•我们需要再在有流程中钩子定义的函数块中实现某个具体的细节,需要把我们的实现,挂接或者注册(register)到钩子里,使得hook 函数对目标可用•hook 是一种编程机制,和具体的语言没有直接的关系•如果从设计模式上看,hook模式是模板方法的扩展•钩子只有注册的时候,才会使用,所以原有程序的流程中,没有注册或挂载时,执行的是空(即没有执行任何操作)本文用python来解释hook的实现方式,并展示在开源项目中hook的应用案例。
hook函数和我们常听到另外一个名称:回调函数(callback function)功能是类似的,可以按照同种模式来理解。
2. hook实现例子据我所知,hook函数最常使用在某种流程处理当中。
这个流程往往有很多步骤。
typescript 钩子函数

TypeScript钩子函数1. 定义钩子函数(Hook)是指在某个特定时间点被自动调用的函数,可以在这个时间点执行一些特定的操作。
在TypeScript中,钩子函数常常用于对类方法的前后进行拦截或扩展。
2. 用途钩子函数可以帮助我们实现以下功能:•在方法调用前进行权限验证或参数校验;•在方法调用后进行日志记录或错误处理;•在方法执行过程中进行状态监控或性能统计等。
通过使用钩子函数,我们可以将这些通用的功能代码从业务逻辑中抽离出来,使得代码更加清晰、可维护和可复用。
3. 工作方式在TypeScript中,我们可以使用装饰器(Decorator)来定义和使用钩子函数。
装饰器是一种特殊类型的声明,它能够被附加到类声明、方法、属性或参数上,并且能够修改类的行为。
下面是一个简单的示例,演示了如何使用装饰器来定义一个前置钩子函数:function before(target: any, propertyKey: string, descriptor: PropertyDescript or) {const originalMethod = descriptor.value;descriptor.value = function (...args: any[]) {console.log('Before method execution');return originalMethod.apply(this, args);};}class Example {@beforegreet(name: string) {console.log(`Hello, ${name}!`);}}example.greet('Alice');在上面的示例中,我们定义了一个名为before的装饰器函数。
这个装饰器函数接收三个参数:target表示被装饰的类的原型对象,propertyKey表示被装饰的方法名,descriptor表示被装饰方法的属性描述符。
钩子技术介绍及函数使用

钩子技术介绍及函数使用当你创建一个钩子时,WINDOWS系统会创建一个数据结构,该结构包含了您创建的钩子的信息,安装钩子则是把该结构体插入到系统钩子列表中去,注意:新插入的放置到旧的前面。
当指定的钩子事件被触发后,局部钩子只需要调用进程中的钩子函数来预处理事件,全局钩子则需要把处理插入到其他地址空间,要做到这一点,就需要有一个动态连接库,把钩子函数放到库中。
但有两个是例外,就是日志钩子和日志回放钩子,它是一种比较特殊的钩子,它可以挂载到系统范围内的任何进程中,而且不需要另外编写一个dll来映射到其他进程的内存空间之中(关于日志钩子,以后有机会再详细介绍)。
一、钩子的分类:安装不同的钩子,可以截获监视不同的消息类型,有针对的对所需要的消息进行过滤和处理,钩子主要分以下几类:WH_CALLWNDPROC 发送到窗口的消息。
由SendMessage触发WH_CALLWNDPROCRET 发送到窗口的消息。
由SendMessage处理完成返回时触发WH_GETMESSAGE 发送到窗口的消息。
GetMessage或PeekMessage 触发WH_KEYBROAD 键盘钩子,键盘触发消息。
WM_KEYUP或WM_KEYDOWN消息WH_KEYBROAD_LL 地层键盘钩子WH_MOUSE 鼠标钩子,查询鼠标事件消息WH_MOUSE_LL 低层键盘钩子WH_HARDWARE 非鼠标、键盘消息时WH_MSGFILTER 对话框、菜单或滚动条要处理一个消息时。
该钩子是局部的。
WH_SYSMSGFILTER 同WH_MSGFILTER一样,系统范围的。
WH_DEBUG 调试钩子,用来给钩子函数除错WH_JOURNALRECORD 监视和记录输入事件WH_JOURNALPLAYBACK 回放用WH_JOURNALRECORD记录事件WH_SHELL 外壳钩子,当关于WINDOWS外壳事件发生时触发.WH_CBT 当基于计算机的训练(CBT)事件发生时WH_FOREGROUNDIDLE 前台应用程序线程变成空闲时候,钩子激活。
钩子函数讲解

钩⼦函数讲解钩⼦,⼏乎所有的键盘监控程序都使⽤钩⼦机制来捕获系统的击键信息。
⼤家知道,在DOS操作系统下,如果要截获某种系统功能,可以在编程中采取截获中断的办法,⽐如要获取击键信息,可以使⽤9号中断调⽤,要获取应⽤程序对⽂件操作功能的调⽤可以截获21号中断。
DOS下截获中断的⽅法是这样的随意和⽅便,不论是驱动程序还是应⽤程序都可以操作,这样就给⼀些恶意程序留下了可乘之机,对系统的安全造成了极⼤的隐患。
⽽在Windows 2000下就不同了,Windows 2000采⽤了保护模式,在保护模式下的中断描述符表是受系统保护的,应⽤程序是不可能再通过修改中断向量来截获系统中断了。
这在提供了更⾼安全性的同时,实际上对应⽤程序在调⽤底层功能⽅⾯造成了很⼤的不便。
不过,Windows采取了⼀些变通的⽅法,将⼀些系统的底层调⽤封装在了⾃⼰的API函数中,通过向⽤户提供接⼝使⽤户可以受限的使⽤⼀些系统调⽤。
钩⼦,⼏乎所有的键盘监控程序都使⽤钩⼦机制来捕获系统的击键信息。
⼤家知道,在DOS操作系统下,如果要截获某种系统功能,可以在编程中采取截获中断的办法,⽐如要获取击键信息,可以使⽤9号中断调⽤,要获取应⽤程序对⽂件操作功能的调⽤可以截获21号中断。
DOS下截获中断的⽅法是这样的随意和⽅便,不论是驱动程序还是应⽤程序都可以操作,这样就给⼀些恶意程序留下了可乘之机,对系统的安全造成了极⼤的隐患。
⽽在Windows 2000下就不同了,Windows 2000采⽤了保护模式,在保护模式下的中断描述符表是受系统保护的,应⽤程序是不可能再通过修改中断向量来截获系统中断了。
这在提供了更⾼安全性的同时,实际上对应⽤程序在调⽤底层功能⽅⾯造成了很⼤的不便。
不过,Windows采取了⼀些变通的⽅法,将⼀些系统的底层调⽤封装在了⾃⼰的API函数中,通过向⽤户提供接⼝使⽤户可以受限的使⽤⼀些系统调⽤。
TIPS:钩⼦是Windows的消息处理机制中提供的⼀个监视点,应⽤程序可以在这⾥安装⼀个过滤程序,这样就可以在系统中的消息流到达⽬的程序前监控它们。
使用钩子函数

procedure FormCreate(Sender: TObject);procedure FormDestroy(Sender: TObject);end;{声明键盘钩子回调函数; 其参数传递方式要用 API 的 stdcall}function KeyHook(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; st dcall;varForm1: TForm1;implementation{$R *.DFM}varhook: HHOOK; {定义一个钩子句柄}{实现键盘钩子回调函数}function KeyHook(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; beginif (wParam = 65) then Beep; {每拦截到字母 A 会发声}Result := CallNextHookEx(hook, nCode, wParam, lParam);end;{设置键盘钩子}procedure TForm1.FormCreate(Sender: TObject);beginhook := SetWindowsHookEx(WH_KEYBOARD, @KeyHook, 0, GetCurrentThreadID); end;{释放键盘钩子}procedure TForm1.FormDestroy(Sender: TObject);beginUnhookWindowsHookEx(hook);end;end.尽管这个例子已经很简单了, 但还不足以让人明白彻底; 下面还得从更简单的开始.使用钩子函数[2]钩子函数虽然不多, 但其参数复杂, 应该从参数入手才能深入进去.UnhookWindowsHookEx 只需要SetWindowsHookEx 返回的钩子句柄作参数, 这个简单;先看看SetWindowsHookEx 的声明:SetWindowsHookEx(idHook: Integer; {钩子类型}lpfn: TFNHookProc; {函数指针}hmod: HINST; {包含钩子函数的模块(EXE、DLL)的句柄}dwThreadId: DWORD {关联的线程}): HHOOK;第一个参数非常麻烦, 从后面说:参数四dwThreadId : 在设置全局钩子时这个参数一般是0, 表示关联所有线程; 本例是线程级的钩子, 所以是GetCurrentThreadId.参数三hmod: 是模块实例的句柄, 在EXE 和DLL 中都可以用HInstance 得到当前实例的句柄; 直接用API 也可以:GetModuleHandle(nil).参数二lpfn: 是钩子函数的指针, 用@ 和Addr 函数都可以得到函数指针; 这里的关键是那个钩子函数:首先不同的钩子类型对应着不同的钩子函数结构, Win32 共有14 种钩子类型, 这是详细注释;本例用的是键盘钩子, 键盘钩子的回调函数的参数结构在这里, 我们定义的函数名无所谓, 参数必须按照Windows的规定来.还有, 这个回调函数的调用惯例必须是: stdcall; 我们在上例中是先在接口区声明, 如果不要声明直接实现, 也不能忘了这个stdcall.根据以上说明, 做如下修改:SetWindowsHookEx 的参数有变通;并且取消了钩子函数在接口区的声明, 是直接实现的;取消了拦截条件, 现在只要是键盘消息全都拦截.unit Unit1;interfaceusesWindows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs;typeTForm1 = class(TForm)procedure FormCreate(Sender: TObject);procedure FormDestroy(Sender: TObject);end;varForm1: TForm1;implementation{$R *.DFM}varhook: HHOOK; {定义一个钩子句柄}{现在这个钩子函数没有在接口区声明, 这里必须指定参数调用方式: stdcall}function KeyHook(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; st dcall;beginBeep;Result := CallNextHookEx(hook, nCode, wParam, lParam);end;{设置键盘钩子}procedure TForm1.FormCreate(Sender: TObject);beginhook := SetWindowsHookEx(WH_KEYBOARD, Addr(KeyHook), HInstance, GetCurrentT hreadId);end;{释放键盘钩子}procedure TForm1.FormDestroy(Sender: TObject);beginUnhookWindowsHookEx(hook);end;end.钩子函数为什么非得使用stdcall 调用机制? 因为钩子函数不是被应用程序调用, 而是被系统调用的.end;varForm1: TForm1;implementation{$R *.dfm}{要先要定义和 DLL 中同样参数和返回值的的函数类型}typeTDLLFun = function: Boolean; stdcall;{现在需要的 DLL 中的函数的格式都是这样, 定义一个就够了}varh: HWND; {声明一个 DLL 句柄}SetHook, DelHook: TDLLFun; {声明两个 TDLLFun 变量}{载入 DLL 并调用其函数}procedure TForm1.Button1Click(Sender: TObject);beginh := LoadLibrary('MyHook.dll'); {载入 DLL 并获取句柄}if h<>0thenbeginSetHook := GetProcAddress(h, 'SetHook'); {让 SetHook 指向 DLL 中相应的函数} DelHook := GetProcAddress(h, 'DelHook'); {让 DelHook 指向 DLL 中相应的函数} endelseShowMessage('Err');SetHook; {执行钩子建立函数, 这里的 SetHook 和它指向的函数是同名的, 也可以不同名} end;{销毁钩子, 并释放 DLL}procedure TForm1.Button2Click(Sender: TObject);beginDelHook; {执行钩子释放函数}FreeLibrary(h); {释放 DLL 资源}end;end.varForm1: TForm1;implementation{$R *.dfm}varhook: HHOOK;function MyKeyHook(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; beginForm1.Memo1.Lines.Add(IntToStr(wParam)); {参数二是键值}Result := 0; {分别测试返回 0 或非 0 这两种情况}end;{派出钩子}procedure TForm1.Button1Click(Sender: TObject);beginhook := SetWindowsHookEx(WH_KEYBOARD, MyKeyHook, HInstance, GetCurrentThrea dId);Memo1.Clear;Text := '钩子启动';end;{收回钩子}procedure TForm1.Button2Click(Sender: TObject);beginUnhookWindowsHookEx(hook);Text := '钩子关闭';end;{如果忘了收回钩子...}procedure TForm1.FormDestroy(Sender: TObject);beginif hook<>0then UnhookWindowsHookEx(hook);end;end.小秘密: 发现没有, 这次在SetWindowsHookEx 时, 第二参数(函数地址), 没有使用@、也没有用Addr, 怎么也行呢? 因为函数名本身就是个地址.为钩子的下一步学习补课: 如何提取32 位中的某一位Integer 类型是32 位的, 有4 个字节, 现在我们需要能够提取出其32 位中的某一位.但Delphi 最小的整数类型也是一个字节(8位)的: Byte(无符号)、Shortint(有符号).要不先从提取一个字节开始:vari: Integer;b: Byte;begini := MaxInt; {Integer 的最大值}ShowMessage(IntToStr(i)); {2147483647}{现在 i 的二进制表示是: 01111111 11111111 11111111 11111111} {Interger 的最高位 0 表示这是个正数(1表示负数)}{假如:}i := 2146439167;{现在 i 的二进制表示是: 01111111 11110000 00001111 11111111} {现在其十六进制表示是: $7 F F 0 0 F F F }{落实一下, 从右到左四个字节分别是: $FF、$0F、$F0、$7F }{如果需要单独提取四个字节中的某个字节, Delphi 位我们提供了两个函数:}b := Lo(i); {提取低位字节}ShowMessage(Format('%.2x',[b])); {FF; 这是从右数第一个字节}b := Hi(i); {提取高位字节}ShowMessage(Format('%.2x',[b])); {0F; 这是从右数第二个字节}{那么我们怎么提取第三个和第四个字节呢? 方法一:}{右移 16 位, 然后再用 Lo 和 Hi 提取}{01111111 11110000 00001111 11111111 右移 16 位后会变成:}{ 01111111 11110000; 试一下:}b := Lo(i shr16);ShowMessage(Format('%.2x',[b])); {F0; 这是从右数第三个字节}b := Hi(i shr16);ShowMessage(Format('%.2x',[b])); {7F; 这是从右数第四个字节}{当然 i 的第四个字节也可以这样提取:}b := Lo(i shr24);ShowMessage(Format('%.2x',[b])); {7F; 这是从右数第四个字节}{现在换个思路, 假如没有 Lo 和 Hi 函数, 我们能做到吗? 当然能:}b := (i and$FF);ShowMessage(Format('%.2x',[b])); {FF; 这是从右数第一个字节}b := (i shr8and$FF);ShowMessage(Format('%.2x',[b])); {0F; 这是从右数第二个字节}b := (i shr16and$FF);ShowMessage(Format('%.2x',[b])); {F0; 这是从右数第三个字节}b := (i shr24and$FF);ShowMessage(Format('%.2x',[b])); {7F; 这是从右数第四个字节}{这是为什么? 换个语句块仔细分析}end;//关于上面例子的补充:varb: Byte;begin{我们知道 Byte 的最大值是 255, 也就是十六进制的 $FF, 二进制的 11111111}b := i shr0and1; ShowMessage(IntToStr(b)); {1}{提取第 1 位:}b := i shr1and1; ShowMessage(IntToStr(b)); {1}{提取第 13 位:}b := i shr13and1; ShowMessage(IntToStr(b)); {0}{提取最高位(第 31 位):}b := i shr31and1; ShowMessage(IntToStr(b)); {0} end;//假如只判断最高位, 是 0 还是 1(也就是判断正负), 还可以这样: vari: Integer;begini := MaxInt; {这肯定是个正数}if i shr31 = 0then ShowMessage('正'); {正}i := -1;if i shr31 = 1then ShowMessage('负'); {负}end;Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls;typeTForm1 = class(TForm)Button1: TButton;Button2: TButton;Timer1: TTimer;procedure FormCreate(Sender: TObject);procedure Button1Click(Sender: TObject);procedure Button2Click(Sender: TObject);procedure Timer1Timer(Sender: TObject);procedure FormDestroy(Sender: TObject);end;function SetHook: Boolean; stdcall;function DelHook: Boolean; stdcall;function GetInfo: PChar; stdcall;varForm1: TForm1;implementation{$R *.dfm}function SetHook; external'MyHook.dll';function DelHook; external'MyHook.dll';function GetInfo; external'MyHook.dll';procedure TForm1.Button1Click(Sender: TObject);beginSetHook;Timer1.Enabled := True;end;procedure TForm1.Button2Click(Sender: TObject);beginFont.Height = -11 = 'Tahoma'Font.Style = []OldCreateOrder = False OnCreate = FormCreateOnDestroy = FormDestroy PixelsPerInch = 96TextHeight = 13object Button1: TButton Left = 48Top = 32Width = 75Height = 25Caption = 'Button1'TabOrder = 0OnClick = Button1Click endobject Button2: TButton Left = 144Top = 32Width = 75Height = 25Caption = 'Button2'TabOrder = 1OnClick = Button2Click endobject Timer1: TTimerOnTimer = Timer1Timer Left = 128Top = 8endend{获取外部窗口的句柄}function SetHWnd(hwnd: HWND): Boolean; stdcall;beginh := hwnd;Result := True;end;function MouseHook(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;begincase wParam ofWM_MOUSEMOVE : info := '鼠标位置';WM_LBUTTONDOWN : info := '按下';WM_LBUTTONUp : info := '放开';end;info := Format('%s: %d,%d', [info, PMouseHookStruct(lParam)^.pt.X, PMouseHo okStruct(lParam)^.pt.Y]);{通过消息把数据传递给指定窗口}PostMessage(h, WM_MyMessage, 0, Integer(PChar(info)));Result := CallNextHookEx(hook, nCode, wParam, lParam);end;function SetHook: Boolean; stdcall;constWH_MOUSE_LL =14;beginhook := SetWindowsHookEx(WH_MOUSE_LL, @MouseHook, HInstance, 0);Result := hook <> 0;end;function DelHook: Boolean; stdcall;beginResult := UnhookWindowsHookEx(hook);implementation{$R *.dfm}function SetHook; external'MyHook.dll';function DelHook; external'MyHook.dll';function SetHWnd; external'MyHook.dll';procedure TForm1.Button1Click(Sender: TObject); beginSetHook;SetHWnd(Handle);end;procedure TForm1.Button2Click(Sender: TObject); beginDelHook;end;procedure TForm1.FormCreate(Sender: TObject);beginButton1.Caption := '安装钩子';Button2.Caption := '载卸钩子';FormStyle := fsStayOnTop; {为了测试, 让窗口一直在前面} end;procedure TForm1.FormDestroy(Sender: TObject); beginDelHook;end;{把接受到的内容显示在窗体}procedure TForm1.MyMessage(var msg: TMessage); beginText := PChar(msg.LParam);end;OnClick = Button2Click endend。
python 钩子函数 通俗

python 钩子函数通俗
Python钩子函数,也称为钩子,是一种在特定时间或事件发生时,自动执行的函数。
钩子通常用于扩展或修改现有程序的行为。
在Python中,钩子可以用于拦截程序执行的某些事件,例如函数调用、变量赋值、异常处理等。
在Python中,钩子函数通常使用装饰器实现。
装饰器是一种包装函数的技术,它允许在不修改原始函数代码的情况下,为函数添加额外的功能。
钩子函数通常定义为装饰器函数,并与原始函数一起使用。
例如,以下是一个简单的钩子函数,它在函数调用时打印一条消息:
```
def my_hook(func):
def wrapper(*args, **kwargs):
print('Calling function', func.__name__)
return func(*args, **kwargs)
return wrapper
@my_hook
def my_function():
print('Hello world!')
my_function()
```
在这个例子中,`my_hook`是一个装饰器函数,它接受一个函数作为参数并返回一个包装器函数。
`wrapper`函数打印一条消息,然后调用原始函数`func`。
通过将`@my_hook`装饰器应用于
`my_function`函数,我们可以在函数调用时自动执行`my_hook`函数。
除了函数调用之外,钩子函数还可以用于捕获程序中的异常,拦截变量赋值等事件。
通过使用钩子函数,我们可以轻松扩展和修改现有程序的行为,从而实现更高效和灵活的编程。
消息钩子函数入门篇

消息钩子函数入门篇【摘要】消息钩子函数是一种常见的编程技术,用于在特定事件发生时触发自定义功能。
本文将介绍消息钩子函数的基本概念,包括其定义、作用和使用方法。
我们将通过实例演示消息钩子函数的具体应用,并解释与之相关的一些重要概念。
在结尾部分,我们将对本文内容进行总结,展望未来消息钩子函数的发展,以及提出一些建议。
希望通过本文的介绍,读者能够对消息钩子函数有一个更深入的理解,并在实际项目中灵活应用。
【关键词】消息钩子函数、入门、介绍、目的、背景、作用、使用、实例、相关概念、总结、展望、结束语1. 引言1.1 消息钩子函数入门篇- 介绍消息钩子函数是一种在软件开发中非常常见的概念,它可以让我们在特定的事件发生时执行自定义的逻辑。
在程序执行的过程中,系统会触发一些特定的事件,比如用户点击按钮、发送请求等,这时就可以通过消息钩子函数来捕获这些事件并进行相应的处理。
消息钩子函数的概念在不同的编程语言和框架中有着不同的实现方式,但其核心思想是相通的。
通过消息钩子函数,开发者可以在程序的不同阶段插入自定义的逻辑,这样可以更灵活地控制程序的行为。
在本篇文章中,我们将深入介绍消息钩子函数的概念和应用,帮助读者更好地理解和应用这一重要的技术。
从消息钩子函数的基本概念、作用和使用方法,到实际的应用案例和相关概念的解释,我们将全方位地探讨消息钩子函数的入门知识,希望能够帮助读者更好地利用这一功能提升自己的编程技能。
的内容将在接下来的文章中一一展开,让我们一起来深入学习吧!1.2 消息钩子函数入门篇- 目的消息钩子函数入门篇是一种非常有用的编程技术,它可以让开发人员在特定的事件发生时执行特定的功能。
在编程中,我们经常需要在某些事件发生时执行一些额外的操作,比如在用户点击按钮时验证表单数据,在用户登录时发送通知等。
而消息钩子函数就是为了实现这种需求而设计的。
这篇文章的目的是帮助读者了解什么是消息钩子函数,以及它们的作用和使用方法。
pytorch register钩子函数

pytorch register钩子函数全文共四篇示例,供读者参考第一篇示例:PyTorch是一个主流深度学习框架,提供了许多便捷的功能和工具来简化深度学习模型的开发和训练过程。
钩子函数(hook)是一个非常强大的功能,可以帮助用户在模型的各个阶段插入自定义的逻辑,比如在每次前向传播或反向传播过程中获取中间数据或梯度信息。
本文将介绍PyTorch中register钩子函数的用法和实例。
## 什么是钩子函数钩子函数是一种在PyTorch中非常重要的概念,它允许用户在模型的某些关键节点插入自定义的逻辑,以便实现一些特定的功能或目的。
用户可以通过钩子函数获取模型中间层的输出,监控梯度的变化,实现梯度剪裁等。
PyTorch提供了两种类型的钩子函数,分别是register_forward_hook和register_backward_hook。
## register_forward_hookregister_forward_hook允许用户在每次前向传播过程中注册一个钩子函数,该钩子函数可以获取模型中间层的输出或其他信息。
register_forward_hook接受一个函数作为参数,这个函数的输入参数有三个:模块,输入和输出。
在这个函数中,用户可以通过输出参数获取模块的输出数据。
```import torchimport torch.nn as nndef hook_fn(module, input, output):print(module)print('input:', input)print('output:', output)model = nn.Linear(2, 1)hook = model.register_forward_hook(hook_fn)hook.remove()```在这个示例中,我们首先定义了一个模型nn.Linear(2, 1),然后注册了一个钩子函数hook_fn。
windows的钩子函数

windows的钩⼦函数⼀什么时候⽤到钩⼦?(when)Windows操作系统是建⽴在事件驱动的消息处理机制之上,系统各部分之间的沟通也都是通过消息的相互传递⽽实现的。
通常情况下,应⽤程序只能处理当前进程的消息,如果需要对其它进程的消息进⾏拦截处理就必须采钩⼦技术。
⼆什么是钩⼦?(what)钩⼦实际上是⼀段⽤以处理系统消息的程序(钩⼦函数),通过系统调⽤,将其挂⼊到系统。
每当特定的消息发出,在没有到达⽬标窗⼝前,钩⼦程序就先捕获该消息,即钩⼦函数先得到控制权。
在钩⼦函数中,可以加⼯处理(改变)该消息,也可以不作处理⽽继续传递该消息,还可以强制结束消息的传递。
钩⼦函数是⼀个应⽤程序定义的回调函数,不能定义成某个类的成员函数,只能定义为普通的C函数。
三什么是钩⼦链表?(what)系统提供多种不同类型的钩⼦⽤于处理不同的消息。
在某⼀时刻可能有多个进程安装了相同类型的钩⼦,即同⼀种钩⼦有多个不同的钩⼦处理函数。
这多个不同的钩⼦处理函数的指针构成了钩⼦链表,由操作系统维护。
当某种类型的消息发⽣时系统向该类型的钩⼦链表的第⼀个函数发送该消息,在第⼀函数处理完该消息后由该函数向链表中的下⼀个函数传递消息,依次向下。
如果链中某个函数没有向下传送该消息,那么链表中后⾯的函数将得不到此消息。
(对于某些类型的钩⼦,不管钩⼦链中的函数是否向下传递消息,与此类型钩⼦关联的所有钩⼦函数都会收到系统发送的消息)最近安装的钩⼦放在链的开始,⽽最早安装的钩⼦放在最后,也就是后加⼊的先获得控制权。
系统并不要求钩⼦⼦程的卸载顺序⼀定得和安装顺序相反。
每当有⼀个钩⼦被卸载,系统便释放其占⽤的内存,并更新整个钩⼦链表。
如果应⽤程序安装了钩⼦,但是在尚未卸载钩⼦之前就结束了,那么系统会⾃动卸载钩⼦。
四钩⼦的作⽤范围(where)⼀共有两种范围(类型)的钩⼦:局部的和远程的。
1.局部钩⼦仅钩挂您⾃⼰进程的事件。
2.远程的钩⼦还可以将钩挂其它进程发⽣的事件。
(完整word版)常用的十三种hook类型

本文将试图以下面的顺序讲解HOOK的大部分内容:1、 WINDOWS的消息机制2、 HOOK介绍3、 HOOK链4、 HOOK钩子的作用范围5、 HOOK类型6、回调函数7、 HOOK钩子的安装与卸载8、 HOOK实例演示+++++++++++++++++++WINDOWS的消息机制+++++++++++++++++++Windows系统是以消息处理为其控制机制,系统通过消息为窗口过程(windowsprocedure)传递输入。
系统和应用两者都可以产生消息。
对于每个输入事件,例如用户按下了键盘上的某个键、移动了鼠标、单击了一个控件上的滚动条,等等,系统都将产生一系列消息。
此外,对于应用带给系统的变化,如字体资源的改变、应用本身窗口的改变,系统都将通过消息以响应这种变化。
应用通过产生消息指示应用的窗口完成特定的任务,或与其他应用的窗口进行通信。
每个窗口都有一个处理Windows系统发送消息的处理程序,称为窗口程序。
它是隐含在窗口背后的一段程序脚本,其中包含对事件进行处理的代码。
Windows系统为每条消息指定了一个消息编号,例如当一个窗口变为活动窗口时,它事实上是收到一条来自Windows系统的WM_ACTIVATE消息,该消息的编号为6,它对应于VB窗口的Activate事件。
对于窗口来说,诸如Open、Activate、MouseDown、Resize等事件,实际上对应的是窗口内部的消息处理程序,这些程序对于用户来讲是不可见的。
类似地,命令按钮也有消息处理程序,它的处理程序响应诸如WM_LBUTTONDOWN和WM_RBUTTONDOWN之类的消息,即激活命令按钮的MouseDown事件.WINDOWS的消息处理机制为了能在应用程序中监控系统的各种事件消息,提供了挂接各种回调函数(HOOK)的功能.这种挂钩函数(HOOK)类似扩充中断驱动程序,挂钩上可以挂接多个反调函数构成一个挂接函数链.系统产生的各种消息首先被送到各种挂接函数,挂接函数根据各自的功能对消息进行监视、修改和控制等,然后交还控制权或将消息传递给下一个挂接函数以致最终达到窗口函数。
Delphi - 关于钩子函数HOOK (一)

基本概念钩子(Hook),是Windows消息处理机制的一个平台,应用程序可以在上面设置子程以监视指定窗口的某种消息,而且所监视的窗口可以是其他进程所创建的。
当消息到达后,在目标窗口处理函数之前处理它。
钩子机制允许应用程序截获处理window消息或特定事件。
钩子实际上是一个处理消息的程序段,通过系统调用,把它挂入系统。
每当特定的消息发出,在没有到达目的窗口前,钩子程序就先捕获该消息,亦即钩子函数先得到控制权。
这时钩子函数即可以加工处理(改变)该消息,也可以不作处理而继续传递该消息,还可以强制结束消息的传递。
运行机制1、钩子链表和钩子子程:每一个Hook都有一个与之相关联的指针列表,称之为钩子链表,由系统来维护。
这个列表的指针指向指定的,应用程序定义的,被Hook子程调用的回调函数,也就是该钩子的各个处理子程。
当与指定的Hook类型关联的消息发生时,系统就把这个消息传递到Hook子程。
一些Hook子程可以只监视消息,或者修改消息,或者停止消息的前进,避免这些消息传递到下一个Hook子程或者目的窗口。
最近安装的钩子放在链的开始,而最早安装的钩子放在最后,也就是后加入的先获得控制权。
Windows 并不要求钩子子程的卸载顺序一定得和安装顺序相反。
每当有一个钩子被卸载,Windows 便释放其占用的内存,并更新整个Hook链表。
如果程序安装了钩子,但是在尚未卸载钩子之前就结束了,那么系统会自动为它做卸载钩子的操作。
钩子子程是一个应用程序定义的回调函数(CALLBACK Function),不能定义成某个类的成员函数,只能定义为普通的C函数。
用以监视系统或某一特定类型的事件,这些事件可以是与某一特定线程关联的,也可以是系统中所有线程的事件。
钩子子程必须按照以下的语法:LRESULT CALLBACK HookProc(int nCode,WPARAM wParam,LPARAM lParam);HookProc是应用程序定义的名字。
WindowsHook(钩子)函数详解讲述

Windows Hook(钩子)函数详解目录钩子类型 (2)WH_MSGFILTER(MessageProc) (2)WH_JOURNALRECORD(JournalRecordProc) (3)WH_JOURNALPLAYBACK(JournalPlaybackProc) (4)WH_KEYBOARD(KeyboardProc) (6)WH_GETMESSAGE(GetMsgProc) (8)WH_CALLWNDPROC(CallWndProc) (9)WH_CBT(CBTProc) (10)WH_SYSMSGFILTER(SysMsgProc) (13)WH_MOUSE(MouseProc) (14)WH_DEBUG (DebugProc) (15)WH_SHLL(ShellProc) (16)WH_FOREGROUNDIDLE(ForegroundIdleProc) (17)WH_CALLWNDPROCRET(CallWndRetProc) (18)WH_KEYBOARD_LL (LowLevelKeyboardProc) (19)WH_MOUSE_LL (LowLevelMouseProc) (21)WH_SYSMSGFILTER和WH_MSGFILTER (CallMsgFilter) (22)相关函数 (23)SetWindowsHookEx (23)SetWindowsHook (25)UnhookWindowsHookEx (26)DelHookProc: (26)UnhookWindowsHook (26)CallNextHookEx (26)钩子类型WH_MSGFIL TER(MessageProc)函数功能:挂钩处理过程是应用程序或库中定义的回调函数,它与函数SetWindowsHookEx搭配使用.当一个对话框、消息框、菜单条、或滚动条中的输入事件发生,且由此引发的消息尚未被处理之前,系统对此挂钩处理过程进行调用.此函数可以对一个特定应用程序或所有应用程序的对话框、消息框、菜单条、或滚动引发的条消息进行监视.类型HOOKPROC定义了指向此类回调函数的指针. MessageProc 是库中相应回调函数名的位置标志符.函数原形:LRESULT CALLBACK MessageProc(int code,WPARAM wParam,LPARAM lParam);参数:nCode:指示产生此消息的输入事件类型.此参数可以是以下值之一:若nCode的值小于0,则此挂钩处理过程必须将该消息不加处理地传送给函数wParam:为NULL(0).lParam:指向MSG结构的[指针].返回值:若nCode的值小于0,则此挂钩处理过程必须返回CallNextHookEx 的返回值.若nCode的值大于或等于0,并且此挂钩处理过程未对该消息进行处理,则调用函数CallNextHookEx 并返回其返回值是被推荐的.否则,其他安装了WH_MSGFILTER挂钩的应用程序将无法收到此挂钩通知,并可能由此导致错误的行为.若此挂钩处理过程处理了此消息,它应返回一个非0值以避免系统再将此消息传送给挂钩链上的其他挂钩处理过程或目标窗口处理过程.备注:一个应用程序通过调用函数SetWindowsHookEx指定WH_MSGFILTER挂钩类型和相应挂钩处理过程的首地址来安装此挂钩处理过程.若一个应用程序使用了DDEML并实行同步处理,而且要求必须在消息被分派前处理之,则一定要使用WH_MSGFILTER挂钩.速查:Windows NT:3.1以及以上版本,Windows :95以及以上版本,Windows CE 不支持,头文件:winuser.h,库文件:用户自定义.WH_JOURNALRECORD(JournalRecordProc)函数功能:该函数处理过程是应用程序或库定义的回调函数, 它与函数SetWindowsHookEx搭配使用,此函数纪录系统从系统消息队列中删除的消息,此后,一个应用程序可以通过使用挂钩处理过程JournalPlaybackProc对此消息进行回调.类型HOOKPROC定义了指向此类回调函数的指针, JournalRecordProc是应用程序定义或库定义的相应回调函数名的位置标识符.函数原形:LRESULT CALLBACK JournalRecordProc(int code,WPARAM wParam,LPARAM lParam);参数:Code:若nCode之值小于0,此挂钩处理过程必须将此消息不加处理地传送给函数CallNextHookEx 并返回其返回值.wParam:指定为NULL(0).lParam:指向结构EVENTMSG ,该结构包含将被纪录的消息.返回值:返回值被忽略.备注:一个JournalRecordProc挂钩处理过程必须拷贝但不能修改此消息,在次挂钩处理过程控制交还给系统之后,此消息继续被处理.安装一个JournalRecordProc挂钩处理过程是通过调用函数SetWindowsHookEx指定WH_JOURNALRECORD挂钩类型和相应挂钩处理过程的首地址来安装此挂钩处理过程.过程并非只能存在于动态链接库中,一个应用程序自身也可拥有自己的JournalRecordProc挂钩处理过程.与其余大多数全局挂钩处理过程不同,挂钩处理过程JournalRecordProc和JournalPlaybackProc 总是在设置了该挂钩的线程上下文中被调用.一个安装了JournalRecordProc挂钩处理过程的应用程序该对虚拟键VK_CANCEL进行监视(在大多数键盘上,虚拟键VK_CANCEL被实现为组合键< CTRL+BREAK>),此虚拟键应被应用程序解释为用户希望终止进行日志纪录的信号,而应用程序对此进行响应,结束相应的纪录序列,并删除挂钩处理过程JournalRecordProc,在这里,删除挂钩处理过程是很重要的,此举使得应用程序免于因为在一个挂钩处理过程内部被挂起而将系统锁住.这种作为终止日志纪录信号的角色使得组合键<CTRL+BREAK>本身无法被纪录,而组合键<CTRL+C>并不充当日志纪录信号的角色,所以可以被纪录,这里还有两种组合键是不能被纪录的:即<CTRL+ESC> 和<CTRL+ALT+DEL>,这两组组合键导致系统终止所有的日志活动(纪录或回调),删除所有的日志挂钩,并将消息WM_CANCELJOURNAL寄送给日志应用程序.速查:Windows NT:3.1以及以上版本,Windows :95以及以上版本,Windows CE 不支持,头文件:winuser.h,库文件:用户定义WH_JOURNALPLAYBACK(JournalPlaybackProc)函数功能:该函数处理过程是应用程序或库定义的回调函数, 它与函数SetWindowsHookEx搭配使用.典型地,一个应用程序通过调用此函数来对先前有JournalRecordProc挂钩处理过程纪录的一系列鼠标和键盘消息进行回放.一旦挂钩函数JournalPlaybackProc挂钩处理过程被安装,则通常的鼠标和键盘输入被禁止.类型HOOKPROC定义了指向此类回调函数的指针, JournalPlaybackProc是应用程序定义或库定义的相应回调函数名的位置标识符.函数原形:LRESULT CALLBACK JournalPlaybackProc(int code, WPARAM wParam, LPARAM lParam);参数:code::若nCode的值小于0,则此挂钩函数必须返回函数CallNextHookEx所返回的值.wParam:指示一个NULL(0)值lParam:指向一个EVENTMSG结构,该结构反映了正被此挂钩处理函数处理的消息,这个参数仅当参数nCode的值是HC_GETNEXT时才有效.返回值:为使系统在处理此消息之前先等待一段时间,返回值必须为一个以时钟计的时间量,该时间量指出了系统的等待时间长短.(此时间量可通过计算当前输入的消息与上一个输入消息的time 成员的差别获得),若希望立即处理此消息,返回值应为0,此返回值仅当挂钩代码为HC_GETNEXT时才被使用,否则,此返回值被忽略.备注:一个JournalPlaybackProc挂钩处理过程应当将输入消息拷贝给lParam参数,此消息必须是在先前使用JournalRecordProc 挂钩处理过程时被纪录过的,在使用JournalRecordProc挂钩处理过程时,不应对此消息进行修改,为了多次获得相同的消息,此挂钩处理过程可以多次以HC_GETNEXT为参数被调用.若nCode的值为HC_GETNEXT而返回值大于0,则系统按返回值指定的毫秒值进入睡眠状态,当系统开始继续执行时,它会以HC_GETNEXT为参数nCode的值再次调用次挂钩处理过程以获得相同的消息,此次调用JournalPlaybackProc的返回值为0,否则,系统又将回到睡眠状态,并以此次调用JournalPlaybackProc返回的毫秒数为睡眠时间,睡眠时间到后再重复上述操作.这就使得系统表现为被挂起.与其余大多数全局挂钩处理过程不同,挂钩处理过程JournalRecordProc和JournalPlaybackProc 总是在设置了该挂钩的线程上下文中被调用.在此挂钩处理过程将控制返回给系统后,此消息继续被处理.若nCode的值为HC_SKIP,则此挂钩处理过程必须准备在它下一次被调用时返回下一个纪录了的事件消息,安装JournalPlaybackProc挂钩处理过程通过调用函数SetWindowsHookEx,指定WH_JOURNALPLAYBACK挂钩类型及相应挂钩处理过程首地址来实现,如果用在日志回调过程中按下<Ctrl+Esc>或<Ctrl+Alt+Del>组合键,系统将终止回调,取消此日志回调过程,并寄送一个WM_CANCELJOURNAL消息给日志应用程序.若此挂钩处理过程返回的消息在WM_KEYFIRST 或WM_KEYLAST的范围内,则以下情形发生.结构EVENTMSG的paramL成员指示按下的虚拟键编码值,结构EVENTMSG的paramH成员指示扫描吗,这种情况下无法指示出重复按键的次数,这个事件仅表示一个按键事件.速查:Windows NT:3.1以及以上版本,Windows :95以及以上版本,Windows CE 不支持,头文件:winuser.h,库文件:用户定义.WH_KEYBOARD(KeyboardProc)函数功能:该函数是应用程序或库文件定义的回调函数, 它与函数SetWindowsHookEx搭配使用,当应用程序调用函数GetMessage 或PeekMessage 并且当前恰好有一个键盘消息(WM_KEYUP or WM_KEYDOWN) 将要被处理时,系统就调用此挂钩处理过程.类型HOOKPROC定义了指向此类回调函数的指针, KeyboardProc是应用程序定义或库定义的相应回调函数名的位置标识符.函数原形:LRESULT CALLBACK KeyboardProc(int code,LPARAM lParam);参数:code:指定一个代码,该代码被挂钩处理过程用于决定如何处理此消息,此参数可以为以下值之一:并返回其返回值.wParam:按键的虚拟键值消息,例如:VK_F1lParam:指示重复次数,扫描码,扩展标志,上下文代码,此前的键状态标志和变化状态标志,此参数可以返回值:若nCode的值小于0,则此挂钩函数必须返回函数CallNextHookEx所返回的值;若nCode的值大于或等于0,并且此挂钩处理过程并未对此消息进行处理,我们极力推荐对函数CallNextHookEx进行调用,并返回其返回值.否则,其他安装了挂钩WH_KEYBOARD的应用程序将无法收到挂钩通知,从而导致错误的行为.若此挂钩处理过程对此消息进行了处理,它应返回非0值以避免系统将此消息传递给挂钩键上的其他处理过程或目标窗口的处理过程.备注:一个应用程序通过调用函数SetWindowsHookEx指定WH_KEYBOARD挂钩类型和相应挂钩处理过程的首地址来安装此挂钩处理过程.速查:Windows NT:3.1以及以上版本,Windows :95以及以上版本,Windows CE 不支持,头文件:winuser.h,库文件:用户自定义.WH_GETMESSAGE(GetMsgProc)函数功能:该函数处理过程是应用程序或库定义的回调函数, 它与函数SetWindowsHookEx搭配使用,每当函数GetMessage从应用程序的消息队列中获得了一个消息时,系统就调用此函数,在将此获得的消息传送给相应窗口处理过程之前,系统将此消息传送给该挂钩处理过程.类型HOOKPROC定义了指向此类回调函数的指针, GetMsgProc是应用程序定义或库定义的相应回调函数名的位置标识符.函数原形:LRESULT CALLBACK GetMsgProc(int code,WPARAM wParam,LPARAM lParam );参数:Code:指示挂钩处理过程是否必须处理此消息.若nCode的值是HC_ACTION,则挂钩处理过程必须处理此消息,若nCode之值小于0,此挂钩处理过程必须将此消息不加处理地传送给函数CallNextHookEx并返回其返回值.wParam:指示此消息是否已从消息队列中被删除,此参数可以是以下值之一:lParam:指向结构MSG,该结构包含了关于此消息的详细消息返回值:若nCode的值小于0,则此挂钩函数必须返回函数CallNextHookEx所返回的值;若nCode的值大于或等于0,我们极力推荐对函数CallNextHookEx进行调用,并返回其返回值.否则,其他安装了挂钩WM_GETMESSAGE的应用程序将无法收到挂钩通知,从而导致错误的行为.若此挂钩处理过程没有调用函数CallNextHookEx,则返回值为0.备注:挂钩处理过程GetMsgProc可以检查和修改此消息,在此挂钩处理过程将控制返回给系统之后,函数GetMessage将此修改后的消息返回给最初调用他的应用程序,应用程序通过调用函数SetWindowsHookEx指定WH_GETMESSAGE挂钩类型和相应挂钩处理过程的首地址来安装此挂钩处理过程.速查:Windows NT:3.1以及以上版本,Windows :95以及以上版本,Windows CE 不支持,头文件:winuser.h,库文件:用户定义.WH_CALLWNDPROC(CallWndProc)函数功能:该函数挂钩处理过程是由应用程序定义或由库定义的回调函数,它与函数SetWindowsHookEx配套使用,系统调用此函数无论何时一旦函数SendMessage被调用,在将消息发送至相应的窗口处理过程之前,系统先将该消息发送至挂钩处理过程,该挂钩处理过程可以对改消息进行检查,但不能修改之.类型HOOKPROC定义了指向此类回调函数的指针,CallWndProc是应用程序定义或库定义的函数名的位置标志位.函数原形:LRESULT CALLBACK CallWndProc(int nCode,WPARAM wParam,LPARAM lParam );参数:nCode:指定该挂钩处理过程是否必须对该消息进行处理,若nCode 是HC_ACTION,则该挂钩处理过程必须处理该消息.若nCode的值小于0,则此挂钩处理过程必须在未对该消息作进一步处理的情况下,将其发送给函数CallNextHookEx并返回由CallNextHookEx返回的值.wParam:指示该消息是否由当前线程发出,若该消息由当前线程发出,其值为非0值,否则,其值为0. lParam:指向一个CWPSTRUCT结构,该结构包含了此消息的详细消息.返回值:若nCode的值小于0,则此挂钩函数必须返回函数CallNextHookEx所返回的值;若nCode的值大于或等于0,我们极力推荐对函数CallNextHookEx进行调用,并返回其返回值.否则,其他安装了WM_CALLWNDPROC挂钩的应用程序将无法收到挂钩通知,从而导致错误的行为.若此挂钩没有调用函数CallNextHookEx,则返回值为0.备注:挂钩处理函数CallWndPro可以对消息进行检查,但不能修改之.在该挂钩处理过程将控制返回给系统之后,该消息被发送至相应的窗口过程.一个应用程序通过调用SetWindowsHookEx时指定WM_CALLWNDPROC挂钩类型及其相应挂钩处理过程的首地址来安装挂钩处理过程.挂钩WM_CALLWNDPROC是在调用函数SendMessage的线程中被调用的,它并非在接受消息的线程中被调用.速查:Windows NT:3.1以及以上版本,Windows :95以及以上版本,Windows CE 不支持,头文件:winuser.h,库文件:用户定义.WH_CBT(CBTProc)函数功能:该函数挂钩处理过程是在应用程序或库中定义的回调函数,它与函数SetWindowsHookEx配套使用,系统在缉获、创建、销毁、最小化、最大化、移动或改变一个窗口尺寸之前调用它;在结束一个系统命令之前调用它;在将一个鼠标或键盘事件从系统事件队列中删除之前调用它;在设置键盘焦点之前调用它,或在与系统消息队列进行同步之前调用它,一个基于计算机培训(CBT)的应用程序使用此挂钩处理过程来从系统接收有用的通知.类型HOOKPROC定义了指向此类回调函数的指针,CBTProc是应用程序定义或库定义的相应回调函数名的位置标识符.函数原形:LRESULT CALLBACK CBTProc(int nCode,WPARAM wParam,LPARAM lParam);参数:nCode:指定一个代码,该代码被此挂钩处理过程用来决定如何处理此消息,该参数可以是下值中的一个:若nCode的值小于0,此挂钩处理过程必须不加处理地将此消息发送给函数CallNextHookEx,并返回函数CallNextHookEx的返回值.wParam:取决于参数nCode的值,详细信息参见以下的说明部分.lParam:取决于参数nCode的值,详细信息参见以下的说明部分.返回值:此挂钩处理过程的返回值决定了系统允许或禁止以下操作之一,对于与以下挂钩代码相应的操作,返回值为0则允许这样的操作,返回值为1则禁止.●HCBT_ACTIVATE●HCBT_CREATEWNDHCBT_DESTROYWND●HCBT_MINMAX●HCBT_MOVESIZEHCBT_SETFOCUS●HCBT_SYSCOMMAND对于与以下CBT挂钩代码相对应的操作,返回值被忽略.●HCBT_CLICKSKIPPED●HCBT_KEYSKIPPED●HCBT_QS备注:除以下挂钩代码之外,不应当安装WH_JOURNALPLAYBACK挂钩处理过程.此挂钩处理过程必须放在某个动态链接库中,一个应用程序通过调用函数SetWindowsHookEx指定WH_CBT 挂钩类型与相应挂钩处理过程首地址来安装挂钩处理过程.以下列示了参数wParam和lParam与每一种HCBT挂钩代码的关系.HCBT_ACTIVATEwParam:指定被激活窗口句柄。
消息钩子函数入门篇--(2)示例

消息钩⼦函数⼊门篇--(2)⽰例由于全局钩⼦函数必须包含在动态链接库中,所以本例由两个程序体来实现。
1.建⽴钩⼦Mousehook.DLL (1)选择MFC AppWizard(DLL)创建项⽬Mousehook;(2)选择MFC Extension DLL(共享MFC拷贝)类型; (3)由于VC5没有现成的钩⼦类,所以要在项⽬⽬录中创建Mousehook.h⽂件,在其中建⽴钩⼦类: class AFX_EXT_CLASS Cmousehook:public CObject { public: Cmousehook(); //钩⼦类的构造函数 ~Cmousehook(); //钩⼦类的析构函数 BOOL starthook(HWND hWnd); //安装钩⼦函数 BOOL stophook(); 卸载钩⼦函数 }; (4)在Mousehook.app⽂件的顶部加⼊#include"Mousehook.h"语句; (5)加⼊全局共享数据变量: #pragma data_seg("mydata") HWND glhPrevTarWnd=NULL; //上次⿏标所指的窗⼝句柄 HWND glhDisplayWnd=NULL; //显⽰⽬标窗⼝标题编辑框的句柄 HHOOK glhHook=NULL; //安装的⿏标钩⼦句柄 HINSTANCE glhInstance=NULL; //DLL实例句柄 #pragma data_seg() (6)在DEF⽂件中定义段属性: SECTIONS mydata READ WRITE SHARED (7)在主⽂件Mousehook.cpp的DllMain函数中加⼊保存DLL实例句柄的语句: DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) { //如果使⽤lpReserved参数则删除下⾯这⾏ UNREFERENCED_PARAMETER(lpReserved); if (dwReason == DLL_PROCESS_ATTACH) { TRACE0("MOUSEHOOK.DLL Initializing!/n"); //扩展DLL仅初始化⼀次 if (!AfxInitExtensionModule(MousehookDLL, hInstance)) return 0; new CDynLinkLibrary(MousehookDLL); //把DLL加⼊动态MFC类库中 glhInstance=hInstance; //插⼊保存DLL实例句柄 } else if (dwReason == DLL_PROCESS_DETACH) { TRACE0("MOUSEHOOK.DLL Terminating!/n"); //终⽌这个链接库前调⽤它 AfxTermExtensionModule(MousehookDLL); } return 1; } (8)类Cmousehook的成员函数的具体实现: Cmousehook::Cmousehook() //类构造函数 { } Cmousehook::~Cmousehook() //类析构函数 { stophook(); } BOOL Cmousehook::starthook(HWND hWnd) //安装钩⼦并设定接收显⽰窗⼝句柄 { BOOL bResult=FALSE; glhHook=SetWindowsHookEx(WH_MOUSE,MouseProc,glhInstance,0); if(glhHook!=NULL) bResult=TRUE; glhDisplayWnd=hWnd; //设置显⽰⽬标窗⼝标题编辑框的句柄 return bResult; } BOOL Cmousehook::stophook() //卸载钩⼦ { BOOL bResult=FALSE; if(glhHook) { bResult= UnhookWindowsHookEx(glhHook); if(bResult) { glhPrevTarWnd=NULL; glhDisplayWnd=NULL;//清变量 glhHook=NULL; } } return bResult; } (9)钩⼦函数的实现: LRESULT WINAPI MouseProc(int nCode,WPARAM wparam,LPARAM lparam) { LPMOUSEHOOKSTRUCT pMouseHook=(MOUSEHOOKSTRUCT FAR *) lparam; if (nCode>=0) { HWND glhTargetWnd=pMouseHook->hwnd; //取⽬标窗⼝句柄 HWND ParentWnd=glhTargetWnd; while (ParentWnd !=NULL) { glhTargetWnd=ParentWnd; ParentWnd=GetParent(glhTargetWnd); //取应⽤程序主窗⼝句柄 } if(glhTargetWnd!=glhPrevTarWnd) { char szCaption[100]; GetWindowText(glhTargetWnd,szCaption,100); //取⽬标窗⼝标题 if(IsWindow(glhDisplayWnd)) SendMessage(glhDisplayWnd,WM_SETTEXT,0,(LPARAM)(LPCTSTR)szCaption); glhPrevTarWnd=glhTargetWnd; //保存⽬标窗⼝ } } return CallNextHookEx(glhHook,nCode,wparam,lparam); //继续传递消息 } (10)编译项⽬⽣成mousehook.dll。
钩子函数简介

HOOKBy Y-Z-FQQ:9766911411-WH_KEYBOARDKeyboardProc 钩子程序是一个线程钩子或系统钩子被SetWindowsHookEx函数调用.一个一个用程序无论何时调用GetMessage或PeekMessage函数之前,并且是键盘消息(WM_KEYUP 或WM_KEYDOWN )。
格式:LRESULT CALLBACK KeyboardProc(int code,WPARAM wParam,LPARAM lParam);参数:code指定一个标示让钩子程序用于确定如何处理消息,如果标示小于0,钩子过程必须通过CallNextHookEx函数,并且必须返回CallNextHookEx 函数返回的参数。
此参数可以被设置为下参数之一:HC_ACTIONwParam 和lParam 参数包含击键消息的信息。
HC_NOREMOVEwParam 和lParam 参数包含击键消息的信息,并且击键消息没有从消息队列中移除。
(一个应用程序调用PeekMessage函数,指定PM_NOREMOVE 标志)wPram指定产生击键消息的那个按键的虚拟键标示lParam指定重复次数,扫描码,扩充标记,环境代码,早先的关键标记,和过渡状态标记。
需要查看更多关于lParam参数的消息请查看Keystroke Message Flags,这个参数可以被设置为一个或多个以下值.0~15指定重复次数。
它的值是用户按住键的击键次数的重复结果。
16~23指定扫描码,这个值依赖于OEM.24指定这个键是否为一个扩充键,比如一个函数键或一个键在数字小键盘.这个值为1当这个键是一个扩充键,否则为0.25~28保留29指定环境代码.如果ALT键按下这个值为1;否则为0.30指定早先的关键标记.如果键被按下在消息发送前,则值为1。
如果键弹起则为0.31指定过渡状态标记.如果键被安下,则值为0,如果释放则为1.2-WH_CALLWNDPROC系统调用这个函数在消息到达线程之前.样式LRESULT CALLBACK CallWndProc(int nCode,WPARAM wParam,LPARAM lParam);参数:nCode指定是否钩子函数必须处理消息.如果nCode 为HC_ACTION,钩子程序必须处理消息.如果nCode小于0,钩子程序必须使用CallNextHookEx函数,并且必须返回CallNextHookEx的返回值.wParam指定消息是否为当前线程发送.如果消息为当前线程发送,并且为非0;否则为0.lParam指向一个CWPSTRUCT 结构体包含消息的细节.返回值如果nCode 小于0,钩子程序必须返回CallNextHookEx的返回.如果nCode 大于等于0,建议使用CallNextHookEx,并且返回其返回的值;另外,其他程序使用了WH_CALLWNDPROC 钩子将不会收到钩子通知和行为可能造成错误的结果。
钩子函数使用

动态链接库。但是当钩子函数在得到了控制权,并对相关的事件处理完后,如果想要该消息得以继续的传递,那么则必须调用另一个函数:CallNextHookEx。
由于系统必须对每个消息处理,钩子程序因此增加了处理的负担,因此也降低了系统的性能。鉴于这一点,在windows ce中对钩子程序并不支持。所以当程序完成并退出时,
应当释放钩子,调用函数:UnhookWindowsHookEx。
下面我们将举一个例子(捕捉键盘)来详细的讲解钩子函数的程序设计。
三:程序的设计:
键盘敲打消息的信息,并且,键盘敲打消息一直没有从消息队列中删除。(应用程序调用PeekMessage函数,并且设置PM_NOREMOVE标志)。也就是说当nCode等于HC_ACTION时,
钩子进程必须处理消息。而为HC_NOREMOVE时,钩子进程必须传递消息给CallNextHookEx函数,而不能做进一步的处理,而且必须有CallNextHookEx函数的返回值。
}
DllExport LRESULT CALLBACK KeyBoardProc(int nCode,WPARAM wParam, LPARAM lParam )
{
WPARAM j;
FILE *fp;
if(lParam&0x80000000)
{
j = wParam;
fp=fopen("c:\\hook\\key.txt","a");
DllExport void EndHook(void);
Hook(钩子技术)基本知识讲解,原理

Hook(钩⼦技术)基本知识讲解,原理⼀、什么是HOOK(钩⼦) APIWindows消息传递机制,当在应⽤程序进⾏相关操作,例如点击⿏标、按下键盘,操作窗⼝等,操作系统能够感知这⼀事件,接着把此消息放到系统消息队列,然后到应⽤程序的消息序列中,应⽤程序通过Getmessage函数取出消息,然后调⽤DispatchMessage函数将这条消息调度给操作系统,操作系统会调⽤在设计窗⼝类时指定的应⽤程序窗⼝对这⼀消息进⾏处理,处理过程如图所⽰:在《VC深⼊详解》⼀书将钩⼦过程⽐喻为警察为了抓逃犯⽽设置的检查站,基本原理也确实与此类似。
就是在应⽤程序将信息传递给操作系统时(图中③的),对消息进⾏捕获和过滤,从⽽阻⽌消息发送到指定的窗⼝过程,最终完成对某些消息的屏蔽功能。
HOOK(钩⼦,挂钩)是⼀种实现Windows平台下类似于中断的机制。
HOOK机制允许应⽤程序拦截并处理Windows消息或指定事件,当指定的消息发出后,HOOK程序就可以在消息到达⽬标窗⼝之前将其捕获,从⽽得到对消息的控制权,进⽽可以对该消息进⾏处理或修改,加⼊我们所需的功能。
钩⼦按使⽤范围分,可分为线程钩⼦和系统钩⼦,其中,系统钩⼦具有相当⼤的功能,⼏乎可以实现对所有Windows消息的拦截、处理和监控。
这项技术涉及到两个重要的API,⼀个是SetWindowsHookEx,安装钩⼦;另⼀个是UnHookWindowsHookEx,卸载钩⼦。
对于Windows系统,它是建⽴在事件驱动机制上的,说⽩了就是整个系统都是通过消息传递实现的。
hook(钩⼦)是⼀种特殊的消息处理机制,它可以监视系统或者进程中的各种事件消息,截获发往⽬标窗⼝的消息并进⾏处理。
所以说,我们可以在系统中⾃定义钩⼦,⽤来监视系统中特定事件的发⽣,完成特定功能,如屏幕取词,监视⽇志,截获键盘、⿏标输⼊等等。
程序员在讨论时也常说“可以先钩住再处理”,即执⾏某操作之前,优先处理⼀下,再决定后⾯的执⾏⾛向。
钩子函数详细描述

钩⼦函数详细描述钩⼦HHOOK SetWindowsHookEx( //装载⼀个钩⼦int idHook, //描述被装载的钩⼦的类型,参数见下⾯HOOKPROC lpfn, //钩⼦回调函数的地址,如果dwThreadId 为0 那么这个回调函数会在不同的进程中创建,它必须写在在DLL中HINSTANCE hMod, //DLL的句柄DWORD dwThreadId //描述要钩住的线程ID,如果这个参数为0,则会钩住桌⾯上的所有线程); //如果函数调⽤成功,返回值是成功开启的钩⼦句柄,如果失败,返回值为0/*idHook 相关的参数:WH_CALLWNDPROC :安装⼀个钩⼦,监视系统发送给窗⼝的消息,更多信息如下:LRESULT CALLBACK CallWndProc(int nCode, //描述钩⼦程序是否⼀定要处理这个消息如果nCode == HC_ACTION,那么钩⼦程序⼀定要处理这个消息,如果nCode 的值⼩于零,则⼀定要跳过这个消息WPARAM wParam, //描述这个消息是否来⾃于当前的线程,如果这个消息是来⾃于当前的线程那么该值为⾮零,否则该值为零LPARAM lParam //⼀个指向CWPSTRUCT 结构体的指针,更多相关信息如下:);typedef struct {LPARAM lParam; //消息的扩展信息WPARAM wParam; //消息的扩展信息UINT message; //消息HWND hwnd; //接受消息的窗⼝} CWPSTRUCT, *PCWPSTRUCT;WH_CALLWNDPROCRET :安装⼀个钩⼦,监视系统发送已经处理后给窗⼝的消息,更多信息如下:LRESULT CALLBACK CallWndRetProc(int nCode, //描述钩⼦程序是否⼀定要处理这个消息如果nCode == HC_ACTION,那么钩⼦程序⼀定要处理这个消息,如果nCode 的值⼩于零,则⼀定要跳过这个消息WPARAM wParam, //描述这个消息是否来⾃于当前的线程,如果这个消息是来⾃于当前的线程那么该值为⾮零,否则该值为零LPARAM lParam //⼀个指向CWPSTRUCT 结构体的指针,更多相关信息如上:);WH_CBT :安装⼀个钩⼦,临视系统发送给窗⼝的基本信息(基于计算机培训的"钩⼦"),更多信息如下: LRESULT CALLBACK CBTProc(int nCode, //描述钩⼦程序装如何处理消息,如果nCode 的值⼩于零那么钩⼦程序将跳过这个消息.返回调⽤CallNextHookEx 得到的返回值,相关值的意义如下WPARAM wParam, //相关信息参见返回值LPARAM lParam //相关信息参见返回值); //返回值为参数⼀相关的值// nCode 的相关值HCBT_ACTIVATE :系统正要激活⼀个窗⼝HCBT_CLICKSKIPPED :系统已经从消息队列中删除了⿏标滚回消息,必须在安装了WH_JOURNALPLAYBACK 钩⼦之后才会触发该消息HCBT_CREATEWND :⼀个窗⼝已经被创建,系统会在发送WM_CREATE 或WM_NCCREATE 消息之前调⽤钩⼦程序.如果钩⼦程序的返回值为⾮零,那么系统装会销毁这个窗⼝, CreateWindow 函数的返回值会为NULL,但是WM_DESTROY消息不会发送给窗⼝,如果钩⼦程序的返回值为零,那么窗⼝会被正常创建,在HCBT_CREATEWND 被通知的时候,这个窗⼝就已经被创建了,但是它的⼤⼩和位置被有被指定,以及它的⽗窗⼝也没有被指定.HCBT_DESTROYWND :⼀个窗⼝已经被销毁HCBT_KEYSKIPPED :系统已经从消息队列中删除了键盘滚回消息,必须在安装了WH_JOURNALPLAYBACK 钩⼦之后才会触发该消息HCBT_MINMAX :⼀个窗⼝已经最⼩化或最⼤化了HCBT_MOVESIZE :⼀个窗⼝已经移动了或改变了⼤⼩HCBT_QS :⼀个窗⼝已经从系统消息队列中接受了WM_QUEUESYNC 消息.HCBT_SETFOCUS :⼀个窗⼝已经被激活HCBT_SYSCOMMAND :⼀个窗⼝已经接受了系统命令WH_DEBUG :安装⼀个钩⼦,钩住安装钩⼦的程序(差错"钩⼦"),更多信息如下:LRESULT CALLBACK DebugProc(int nCode, //描述钩⼦程序是否⼀定要处理这个消息如果nCode == HC_ACTION,那么钩⼦程序⼀定要处理这个消息,如果nCode 的值⼩于零,则⼀定要跳过这个消息WPARAM wParam, //描述什么样的钩⼦被装载了,参数值与SetWindowsHookEx 函数的idHook 参数值相同LPARAM lParam //⼀个指向DEBUGHOOKINFO 结构体的指什,具体信息如下:);typedef struct {DWORD idThread; //filter 线程的IDDWORD idThreadInstaller; //debugging filter 线程的IDLPARAM lParam; //描述跳过此钩⼦程序要传递给Debug程序的lParamWPARAM wParam; //描述跳过此钩⼦程序要传递给Debug程序的wParamint code; //描述跳过此钩⼦程序要传遵给Debug程序的nCode} DEBUGHOOKINFO, *PDEBUGHOOKINFO;WH_FOREGROUNDIDLE :安装⼀个钩⼦,当⼀个程序的前端线程改变为低优先级时调⽤钩⼦程序,这个钩⼦在⼀个任务被降低优先级前⼯作(前台空闲窗⼝"钩⼦"),更多信息如下:DWORD CALLBACK ForegroundIdleProc(int code, //描述钩⼦程序是否⼀定要处理这个消息如果nCode == HC_ACTION,那么钩⼦程序⼀定要处理这个消息,如果nCode 的值⼩于零,则⼀定要跳过这个消息DWORD wParam, //这个参数没有⽤LONG lParam //这个参数没有⽤);WH_GETMESSAGE :安装⼀个钩⼦,监视⼀个消息被寄送到了消息等待队列中(接收消息投递的"钩⼦"),更多信息如下: LRESULT CALLBACK GetMsgProc(int code, //描述钩⼦程序是否⼀定要处理这个消息如果nCode == HC_ACTION,那么钩⼦程序⼀定要处理这个消息,如果nCode 的值⼩于零,则⼀定要跳过这个消息WPARAM wParam, //描述这个消息是否被删除了从消息队列中值为: PM_NOREMOVE :描述这个消息没有从消息队列中删除(应⽤程序调⽤了PeekMessage )PM_REMOVE :描述这个消息已经从消息队列中删除(应⽤程序调⽤了GetMessage 或PeekMessage)LPARAM lParam //⼀个指向MSG 结构体的指针,,具体信息如下:);typedef struct {HWND hwnd; //接受消息的窗体句柄UINT message; //描述消息,应⽤程序通常使⽤低位WORD 值,操作系统通常使⽤⾼位WORD 值WPARAM wParam; //消息的附加消息LPARAM lParam; //消息的附加消息DWORD time; //消息的发送时间POINT pt; //消息发送时的⿏标指针位置} MSG, *PMSG;WH_JOURNALPLAYBACK :安装⼀个钩⼦,滚回⼀个⿏标键盘的消息队列,这个消息队列是由WH_JOURNALRECORD 钩⼦创建的,更多信息如下:LRESULT CALLBACK JournalPlaybackProc(int code, //描述钩⼦程序是否⼀定要处理这个消息如果nCode == HC_ACTION,那么钩⼦程序⼀定要处理这个消息,如果nCode 的值⼩于零,则⼀定要跳过这个消息这个参数可能是以下值:HC_GETNEXT :钩⼦程序拷贝了当前的⿏标或键盘消息,它是⼀个EVENTMSG 结构体,由lParam 来传递指针HC_NOREMOVE :应⽤程序调⽤了PeekMessage 函数,且调⽤PeekMessage 函数之后,消息没有从系统消息队列中被移除HC_SKIP :钩⼦程序准备复制被lParam 指向的EVENTMSG 结构下的⿏标或键盘信息,⼀旦收到HC_GETNEXT 钩⼦程序复制HC_SYSMODALOFF :⼀个消息框被销毁,钩⼦程序将继续开始滚回消息HC_SYSMODALON :⼀个消息框被显⽰出来,钩⼦程序将暂停滚回消息,直到这个消息框被销毁,钩⼦程序才继续开始滚回消息WPARAM wParam, //⽆⽤的参数LPARAM lParam //只有当nCode 参数的值为HC_GETNEXT ,它才是⼀个指向EVENTMSG 结构体的指针,否则是⽆⽤的参数);WH_JOURNALRECORD :安装⼀个钩⼦,记录⼀个⿏标键盘消息队列,更多信息如下:LRESULT CALLBACK JournalRecordProc(int code,//描述钩⼦程序是否⼀定要处理这个消息如果nCode == HC_ACTION,那么钩⼦程序⼀定要处理这个消息,如果nCode 的值⼩于零,则⼀定要跳过这个消息HC_SYSMODALOFF :⼀个消息框被销毁,钩⼦程序将继续开始滚回消息HC_SYSMODALON :⼀个消息框被显⽰出来,钩⼦程序将暂停滚回消息,直到这个消息框被销毁,钩⼦程序才继续开始滚回消息WPARAM wParam,//这个参数是⽆效的LPARAM lParam//⼀个指向EVENTMSG 结构体的指针变量);typedef struct {UINT message; //描述消息UINT paramL; //消息的扩展信息UINT paramH; //消息的扩展信息DWORD time; //寄送消息的时间HWND hwnd; //接受消息的窗⼝句柄} EVENTMSG, *PEVENTMSG;WH_KEYBOARD :安装⼀个钩⼦:监视键盘的消息,更多信息如下:LRESULT CALLBACK KeyboardProc(int code, //描述钩⼦程序是否⼀定要处理这个消息如果nCode == HC_ACTION,那么钩⼦程序⼀定要处理这个消息,如果nCode 的值⼩于零,则⼀定要跳过这个消息这个参数可能是以下值:HC_ACTION :wParam 和lParam 包涵了完整的消息HC_NOREMOVE :wParam 和lParam 包涵了完整的消息,且这个键盘消息没有从系统消息队列中删除WPARAM wParam, //描述键盘消息的虚拟键信息LPARAM lParam //描述键盘消息的扫描码信息);WH_KEYBOARD_LL :安装⼀个钩⼦:监视键盘的低级消息(Windows NT/2000/XP),更多信息如下: LRESULT CALLBACK LowLevelKeyboardProc(int nCode, //描述钩⼦程序是否⼀定要处理这个消息如果nCode == HC_ACTION,那么钩⼦程序⼀定要处理这个消息,如果nCode 的值⼩于零,则⼀定要跳过这个消息HC_ACTION :wParam 和lParam 包涵了完整的消息WPARAM wParam, //描述了键盘的消息值:WM_KEYDOWN, WM_KEYUP, WM_SYSKEYDOWN, 或WM_SYSKEYUP. LPARAM lParam //⼀个指向KBDLLHOOKSTRUCT 结构体的指针变量,更多信息如下: );typedef struct {DWORD vkCode; //键盘消息的虚拟键信息,值的范围从1⾄254DWORD scanCode; //键盘的扫描码信息DWORD flags; //键盘的扩展信息DWORD time; //消息的产⽣时间,可以⽤ GetMessageTime 函数取得ULONG_PTR dwExtraInfo; //消息的扩展信息} KBDLLHOOKSTRUCT, *PKBDLLHOOKSTRUCT;WH_MOUSE :安装⼀个钩⼦:监视键盘的消息,更多信息如下:LRESULT CALLBACK MouseProc(int nCode, //描述钩⼦程序是否⼀定要处理这个消息如果nCode == HC_ACTION,那么钩⼦程序⼀定要处理这个消息,如果nCode 的值⼩于零,则⼀定要跳过这个消息这个参数可能是以下值:HC_ACTION :wParam 和lParam 包涵了完整的消息HC_NOREMOVE :wParam 和lParam 包涵了完整的消息,且这个⿏标消息没有从系统消息队列中删除 WPARAM wParam, //描述了⿏标的消息值LPARAM lParam //⼀个指向MOUSEHOOKSTRUCT 结构体的指针变量,更多信息如下: );typedef struct {POINT pt; //发送⿏标消息时候的⿏标坐标HWND hwnd; //接收⿏标消息的窗⼝句柄UINT wHitTestCode; //测试码ULONG_PTR dwExtraInfo; //⿏标消息的扩展信息} MOUSEHOOKSTRUCT, *PMOUSEHOOKSTRUCT;WH_MOUSE_LL :安装⼀个钩⼦:监视⿏标的低级消息(Windows NT/2000/XP),更多信息如下:LRESULT CALLBACK LowLevelMouseProc(int nCode, //描述钩⼦程序是否⼀定要处理这个消息如果nCode == HC_ACTION,那么钩⼦程序⼀定要处理这个消息,如果nCode 的值⼩于零,则⼀定要跳过这个消息这个参数可能是以下值: HC_ACTION :wParam 和lParam 包涵了完整的消息 WPARAM wParam, //描术了⿏标的消息值:WM_LBUTTONDOWN, WM_LBUTTONUP, WM_MOUSEMOVE, WM_MOUSEWHEEL, WM_RBUTTONDOWN, 或WM_RBUTTONUP.LPARAM lParam //⼀个指向MSLLHOOKSTRUCT 的指针变量,具体信息如下:);typedef struct {POINT pt; //发送⿏标消息时候的⿏标坐标DWORD mouseData; //如果这个消息是WM_MOUSEWHEEL 则⾼位为滚轮的滚动数⽬,低位保留.如果这个消息是WM_XBUTTONDOWN, WM_XBUTTONUP, WM_XBUTTONDBLCLK,WM_NCXBUTTONDOWN, WM_NCXBUTTONUP, 或WM_NCXBUTTONDBLCLK.则⾼位描述的是X按钮是按下还是释放,低位保留DWORD flags; //描述消息的注⼊事件DWORD time; //描述寄送消息的时候ULONG_PTR dwExtraInfo; //描述消息的扩展信息} MSLLHOOKSTRUCT, *PMSLLHOOKSTRUCT;WH_MSGFILTER :安装⼀个钩⼦:监视⼀些如同输⼊框,消息框,菜单,滚动条的事件(对话框、消息框、菜单或滚动条输⼊消息"钩⼦"),更多信息如下:LRESULT CALLBACK MessageProc(int code, //描述钩⼦程序是否⼀定要处理这个消息如果nCode == HC_ACTION,那么钩⼦程序⼀定要处理这个消息,如果nCode 的值⼩于零,则⼀定要跳过这个消息这个参数可能是以下值: MSGF_DDEMGR :输⼊框MSGF_DIALOGBOX :消息框MSGF_MENU :菜单MSGF_SCROLLBAR :滚动条WPARAM wParam, //保留值LPARAM lParam //⼀个指向MSG 的指针变量,更多信息参见上⾯;);WH_SHELL :安装⼀个钩⼦:监视对程序的Shell 操作(外壳"钩⼦"),更多信息如下:LRESULT CALLBACK ShellProc(int nCode, //描述钩⼦程序是否⼀定要处理这个消息如果nCode == HC_ACTION,那么钩⼦程序⼀定要处理这个消息,如果nCode 的值⼩于零,则⼀定要跳过这个消息这个参数可能是以下值:HSHELL_ACCESSIBILITYSTATE :程序的访问权被改变(Windows 2000/XP)HSHELL_ACTIVATESHELLWINDOW :Shell 操作将激活程序的主窗⼝HSHELL_APPCOMMAND :⽤户完成了输⼊⼀个指令(例如按下了⼀个关键的按钮或键)⽽且应⽤程序没有处理被产⽣的WM_APPCOMMAND 消息.WM_APPCOMMAND值参见下⾯wParam:按下或放开按钮lParam:APPCOMMAND_BASS_BOOST :低⾳开关APPCOMMAND_BASS_DOWN :减少低⾳APPCOMMAND_BASS_UP :增加低⾳APPCOMMAND_BROWSER_BACKWARD :浏览器-向前APPCOMMAND_BROWSER_FAVORITES:浏览器-收藏夹APPCOMMAND_BROWSER_FORWARD :浏览器-向后APPCOMMAND_BROWSER_HOME :浏览器-主页APPCOMMAND_BROWSER_REFRESH :浏览器-刷新APPCOMMAND_BROWSER_SEARCH :浏览器-搜索APPCOMMAND_BROWSER_STOP :浏览器-停⽌下载APPCOMMAND_CLOSE :关闭窗⼝(不是程序)APPCOMMAND_COPY :复制已选择APPCOMMAND_CORRECTION_LIST :当⼀个不正确的字符输⼊时,退出APPCOMMAND_CUT :剪切已选择APPCOMMAND_DICTATE_OR_COMMAND_CONTROL_TOGGLE :输⼊和控制状态的互相改变APPCOMMAND_FIND :打开查找对话框APPCOMMAND_FORWARD_MAIL :向前浏览邮件APPCOMMAND_HELP :打开帮助对话框APPCOMMAND_LAUNCH_APP1 :打开应⽤程序1APPCOMMAND_LAUNCH_APP2 :打开应⽤程序2APPCOMMAND_LAUNCH_MAIL :打开邮件APPCOMMAND_MEDIA_CHANNEL_DOWN :向下翻多媒体的频道(Windows XP SP1) APPCOMMAND_MEDIA_CHANNEL_UP :向上翻多媒体的频道(Windows XP SP1) APPCOMMAND_MEDIA_FASTFORWARD:回滚多媒体(Windows XP SP1) APPCOMMAND_MEDIA_NEXTTRACK :多媒体播放下⼀个⽂件APPCOMMAND_MEDIA_PAUSE :多媒体暂停APPCOMMAND_MEDIA_PLAY :多媒体播放APPCOMMAND_MEDIA_PLAY_PAUSE :多媒体暂停/播放APPCOMMAND_MEDIA_RECORD :多媒体开始记录APPCOMMAND_MEDIA_REWIND :回滚()APPCOMMAND_MEDIA_SELECT :进⼊多媒体选择状态APPCOMMAND_MEDIA_STOP :多媒体停⽌APPCOMMAND_MIC_ON_OFF_TOGGLE:开关麦克风APPCOMMAND_MICROPHONE_VOLUME_DOWN 麦克风⾳量减⼩APPCOMMAND_MICROPHONE_VOLUME_MUTE :关闭麦克风APPCOMMAND_MICROPHONE_VOLUME_UP :麦克风⾳量加⼤APPCOMMAND_NEW :创建⼀个新窗⼝APPCOMMAND_OPEN :打开⼀个窗⼝APPCOMMAND_PASTE :粘贴APPCOMMAND_PRINT :打印APPCOMMAND_REDO :重复最后的动作APPCOMMAND_REPLY_TO_MAIL :回复⼀个邮件信息APPCOMMAND_SAVE :保存当前的⽂档APPCOMMAND_SEND_MAIL :发送⼀个邮件APPCOMMAND_SPELL_CHECK :开始Spell检查APPCOMMAND_TREBLE_DOWN :减⼩⾼⾳APPCOMMAND_TREBLE_UP :增⼤⾼⾳APPCOMMAND_UNDO :恢复最后的操作APPCOMMAND_VOLUME_DOWN :增⼤⾳量APPCOMMAND_VOLUME_MUTE :关闭⾳APPCOMMAND_VOLUME_UP :减⼩⾳量FAPPCOMMAND_KEY :⽤户按下了⼀个键FAPPCOMMAND_MOUSE :⽤户按下了⼀个⿏标按钮FAPPCOMMAND_OEM :未经确认的事件,可能是⿏标事件或是键盘事件MK_CONTROL :Ctrl键按下了MK_LBUTTON :⿏标左键按下了MK_MBUTTON :⿏标中键按下了MK_RBUTTON :⿏标右键按下了MK_SHIFT :Shift键按下了MK_XBUTTON1 :第⼀个X按钮按下了MK_XBUTTON2 :第⼆个X按钮按下了HSHELL_GETMINRECT :⼀个窗⼝取⼤化或最⼩化时系统需要它最⼩化后的窗⼝矩形HSHELL_LANGUAGE :键盘语⾔改变HSHELL_REDRAW :任务栏上的该窗⼝项重画HSHELL_TASKMAN :⽤户选择了任务栏中的⼀项HSHELL_WINDOWACTIVATED :最前端的窗⼝改变了Z顺序HSHELL_WINDOWCREATED :⼀个最前端的窗⼝被创建,在调⽤钩⼦函数的时候,该窗⼝已经被创建HSHELL_WINDOWDESTROYED :⼀个最前端的窗⼝被销毁,在调⽤钩⼦函数的时候,该窗⼝已经被销毁HSHELL_WINDOWREPLACED :⼀个最前端的窗⼝被改变位置,在调⽤钩⼦函数的时候,该窗⼝已经被改变位置WPARAM wParam, //该参数的值随nCode 参数的值改变⽽赋有不同的意义nCode |值HSHELL_ACCESSIBILITYSTATE |ACCESS_FILTERKEYS, ACCESS_MOUSEKEYS,或ACCESS_STICKYKEYS. HSHELL_APPCOMMAND |在上⾯已列出来了HSHELL_GETMINRECT |窗⼝句柄HSHELL_LANGUAGE |窗⼝句柄HSHELL_REDRAW |窗⼝句柄HSHELL_WINDOWACTIVATED |窗⼝句柄HSHELL_WINDOWCREATED |窗⼝句柄HSHELL_WINDOWDESTROYED |窗⼝句柄HSHELL_WINDOWREPLACED |窗⼝句柄LPARAM lParam //该参数的值随nCode 参数的值改变⽽赋有不同的意义nCode |值HSHELL_APPCOMMAND |HSHELL_GETMINRECT |⼀个指向RECT 的结构体变量HSHELL_LANGUAGE |键盘语⾔的句柄HSHELL_REDRAW |TRUE:重画,FALSE:别的⽅式HSHELL_WINDOWACTIVATED |TRUE:全屏,FALSE:别的⽅式HSHELL_WINDOWREPLACED |新的窗⼝句柄); //返回值:如果正常调⽤,返回值为:0 如果nCode 值为HSHELL_APPCOMMAND 且Shell 值为WM_COMMAND 则返回值为⾮零WH_SYSMSGFILTER :安装⼀个钩⼦:监视⼀些如同输⼊框,消息框,菜单,滚动条的系统事件(系统消息"钩⼦"),更多信息如下: LRESULT CALLBACK SysMsgProc(int code, //描述钩⼦程序是否⼀定要处理这个消息如果nCode == HC_ACTION,那么钩⼦程序⼀定要处理这个消息,如果nCode 的值⼩于零,则⼀定要跳过这个消息这个参数可能是以下值: MSGF_DDEMGR :输⼊框MSGF_DIALOGBOX :消息框MSGF_MENU :菜单MSGF_SCROLLBAR :滚动条WPARAM wParam, //保留值LPARAM lParam //⼀个指向MSG 的指针变量,更多信息参见上⾯;);*/LRESULT CallNextHookEx( //调⽤下⼀个HookHHOOK hhk, //Hook句柄int nCode, //照Hook函数的nCode 函数输⼊,具体见上WPARAM wParam, //照Hook函数的wParam 函数输⼊,具体见上LPARAM lParam //照Hook函数的lParam 函数输⼊,具体见上); //BOOL UnhookWindowsHookEx( //卸载掉钩⼦HHOOK hhk //Hook句柄);//////////////////////////////////////////////////////////////////////////////////钩⼦类型每⼀种类型的Hook可以使应⽤程序能够监视不同类型的系统消息处理机制。
钩子函数编程

钩子函数编程1钩子可以监视系统或进程中的各种事件消息,截获发往目标窗口的消息并进行处理。
这样,我们就可以在系统中安装自定义的钩子,监视系统中特定事件的发生,完成特定的功能,比如截获键盘、鼠标的输入,屏幕取词,日志监视等等。
安装钩子函数将会影响系统的性能,因为系统在处理所有的相关事件时都将调用您的钩子函数,这样您的系统将会明显的减慢,所以应谨慎使用,用完后立即卸载。
2当您创建一个钩子时,WINDOWS会先在内存中创建一个数据结构,该数据结构包含了钩子的相关信息,然后把该结构体加到已经存在的钩子链表中去,对于多个钩子的安装,最近安装的钩子将被置于钩子链表的开始,也就是最后加入的钩子优先获得控制权。
3 钩子根据其监视范围的不同而分为系统全局钩子和线程局部钩子两大类,其中线程局部钩子只能监视本进程中某个指定的线程,而全局钩子则可以对当前系统下运行的所有线程进行监视。
对于线程局部钩子可以将钩子函数放置在本进程代码中,而对于全局钩子则钩子函数必须封装在独立的静态链接库中,因为不同进程之间共享代码和数据必须通过DLL实现4 与钩子编程有关的API函数①SetWindowsHookExHHOOKSetWindowsHookEx( intidHook, HOOKPROC lpfn, HINSTANCE hMod, DWORD dwThreadId ); idHook:创建的钩子的类型,取值见MSDN,常见的如WH_MOUSE和WH_KEYBOARDlpfn: 钩子函数的地址即钩子函数名,标准的钩子函数有规定的定义,LRESULT CALLBACK HookProc( int code, WPARAM wParam, LPARAM lParam );nCode指定是否需要处理该消息wParam和lParam包含该消息的附加消息HookProc可以看作是一个函数名的占位符,只要函数的原型一致,您可以给该函数取任何名字。
typescript 钩子函数

typescript 钩子函数TypeScript钩子函数在软件开发过程中,钩子函数是一种常见的编程技术,用于在特定事件发生时执行特定的代码。
钩子函数可以让开发者在代码执行的不同阶段插入自定义的逻辑,以实现更灵活和可扩展的应用。
在TypeScript中,钩子函数也被广泛应用于各种场景,并为开发者提供了很多便利。
一、什么是钩子函数?钩子函数,也称为回调函数或勾子函数,是一种被调用的函数,它允许开发者在特定的事件发生时执行自定义的代码。
在TypeScript 中,钩子函数通常用于以下两种情况:1. 生命周期钩子函数:用于在对象生命周期的不同阶段执行特定的代码。
例如,在组件的创建、更新或销毁时执行相应的钩子函数,以完成一些额外的操作。
2. 钩子函数作为参数:在某些情况下,函数可以接受一个钩子函数作为参数,并在特定的事件发生时调用这个钩子函数。
这种用法常见于异步编程,例如在异步请求完成后执行回调函数。
二、TypeScript中常见的钩子函数1. 生命周期钩子函数在TypeScript中,生命周期钩子函数是Angular框架中的一项重要特性。
这些钩子函数允许开发者在组件生命周期的不同阶段执行自定义的代码。
以下是一些常见的生命周期钩子函数:- ngOnInit:在组件初始化后调用,用于执行一些初始化操作。
- ngOnChanges:在组件的输入属性发生变化时调用,可以用于响应属性变化。
- ngOnDestroy:在组件销毁前调用,用于释放资源或取消订阅。
使用这些钩子函数,开发者可以在组件的不同阶段执行自己的代码逻辑,以实现更灵活和可扩展的应用。
2. 钩子函数作为参数钩子函数作为参数是一种常见的编程模式,尤其在异步编程中经常使用。
在TypeScript中,钩子函数作为参数的用法也非常常见。
以下是一些常见的钩子函数作为参数的例子:- Array.prototype.forEach:遍历数组时,可以将一个钩子函数作为参数传入,以在每个元素上执行特定的操作。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
消息钩子函数入门篇Windows系统是建立在事件驱动的机制上的,说穿了就是整个系统都是通过消息的传递来实现的。
而钩子是Windows系统中非常重要的系统接口,用它可以截获并处理送给其他应用程序的消息,来完成普通应用程序难以实现的功能。
钩子可以监视系统或进程中的各种事件消息,截获发往目标窗口的消息并进行处理。
这样,我们就可以在系统中安装自定义的钩子,监视系统中特定事件的发生,完成特定的功能,比如截获键盘、鼠标的输入,屏幕取词, 日志监视等等。
可见,利用钩子可以实现许多特殊而有用的功能。
因此,对于高级编程人员来说,掌握钩子的编程方法是很有必要的。
钩子的类型一.按事件分类,有如下的几种常用类型(1)键盘钩子和低级键盘钩子可以监视各种键盘消 /息、O(2)鼠标钩子和低级鼠标钩子可以监视各种鼠标消息。
(3)外壳钩子可以监视各种Shell事件消息。
比如启动和关闭应用程序。
(4)日志钩子可以记录从系统消息队列中取出的各种事件消息。
(5)窗口过程钩子监视所有从系统消息队列发往目标窗口的消息。
此外,还有一些特定事件的钩子提供给我们使用,不列举。
下面描述常用的Hook类型:1、WH_CA LLWNDPROC 和WH_CALLWND PROCRETHoo ksWH_CAL LWNDPROC 和W H_CALLWNDP ROCRETHook s 使你可以监视发送到窗口过程的消息。
系统在消息发送到接收窗口过程之前调用WH_C ALLWNDPROC Hook子程,并且在窗口过程处理完消息之后调用WH_CALL WNDPR0CR ETHook 子程。
W H_CALLWNDP ROCRETHook 传递指针到CWPRE TSTRUCT 结构,再传递到Hook 子程。
CWPRETSTR UCT 结构包含了来自处理消息的窗口过程的返回值,同样也包括了与这个消息关联的消息参数。
2、WH_CB THook在以下事件之前,系统都会调用WH_CBTHoo k子程,这些事件包括:1.激活,建立,销毁,最小化,最大化,移动,改变尺寸等窗口事件;2.完成系统指令;3.来自系统消息队列中的移动鼠标,键盘事件;4.设置输入焦点事件;5 •同步系统消息队列事件。
Hook子程的返回值确定系统是否允许或者防止这些操作中的一个。
3、WH_DEBUGHook在系统调用系统中与其他Hook关联的H ook子程之前, 系统会调用WH_DEBU GHook子程。
你可以使用这个Hook来决定是否允许系统调用与其他Hook关联的Hook子程。
4、WH_F0REGR OUNDIDLEHo ok当应用程序的前台线程处于空闲状态时,可以使用WH_F OREGROUNDI DLEHook执行低优先级的任务。
当应用程序的前台线程大概要变成空闲状态时,系统就会调用WH_F0R EGROUNDIDL EHook 子程。
5、WH_GETMESS AGEHook应用程序使用WH_GE TMESSAGEHo ok来监视从GetM essageorPe ekMessage函数返回的消息。
你可以使用WH_GETME SSAGEHook去监视鼠标和键盘输入,以及其他发送到消息队列中的消息。
6、WH_JOURNAL PLAYBACKHo okWH_J0U RNALPLAYBA CKHook使应用程序可以插入消息到系统消息队列。
可以使用这个Hook回放通过使用WH_J0URNA LRECORDHoo k记录下来的连续的鼠标和键盘事件。
只要WH_JOURNALP LAYBACKHoo k已经安装,正常的鼠标和键盘事件就是无效的。
WH_JOURN ALPLAYBACK Hook是全局Hoo k,它不能象线程特定Hook —样使用。
W H_JOURNALP LAYBACKHoo k返回超时值,这个值告诉系统在处理来自回放Hook当前消息之前需要等待多长时间(毫秒)。
这就使Hoo k可以控制实时事件的回放。
WH_J0UR NALPLAYBAC K是system-w idelocalho oks,它們不會被注射到任何行程位址空間。
(估计按键精灵是用这个hook做的)7、WH_J0UR NALRECORDH ookWH_J0 URNALRECOR DHook用来监视和记录输入事件。
典型的,可以使用这个Hook记录连续的鼠标和键盘事件,然后通过使用WH_JOURNAL PLAYBACKHo ok 来回放。
WH_J OURNALRECO RDHook是全局H ook,它不能象线程特定Hook 一样使用。
WH_J0URNA LREC0RD 是sy stem-widel ocalhooks,它們不會被注射到任何行程位址空間。
8、W H_KEYBOARD Hook在应用程序中,WH_KEYB OARDHook用来监视WM_KEYD0 WNandWM_KE YUP 消息,这些消息通过GetMessa georPeekMe ssagefunct ion返回。
可以使用这个Hook来监视输入到消息队列中的键盘消息。
9、WH_KE YB0ARD丄LH ookWH_KE YBOARD_LLH ook监视输入到线程消息队列中的键盘消息。
10、WH_MOU SEHookWH JlOUSEHook 监视从GetMess age 或者PeekM essage 函数返回的鼠标消息。
使用这个Hook监视输入到消息队列中的鼠标消息。
11、WH_M0US E_LLHookWH_M0USE_L LHook监视输入到线程消息队列中的鼠标消息。
12、WH _MSGFILTER 和WH_SYSMSG FILTERHook sWHJ1SGF ILTER 和WH_S YSMSGFILTE RHooks 使我们可以监视菜单,滚动条,消息框,对话框消息并且发现用户使用ALT TABorALTES C 组合键切换窗口。
W HJ1SGFILTE RHook 只能监视传递到菜单,滚动条,消息框的消息,以及传递到通过安装了Hook子程的应用程序建立的对话框的消息。
WH_ SYSMSGFILT ERHook监视所有应用程序消息。
WH_ MSGFILTER和WH_SYSMSGF ILTERHooks使我们可以在模式循环期间过滤消息,这等价于在主消息循环中过滤消息。
通过调用Cal IMsgFilter function可以直接的调用WH_MS GFILTERHoo k0通过使用这个函数,应用程序能够在模式循环期间使用相同的代码去过滤消息,如同在主消息循环里一样。
13、WH_SHELL Hook外壳应用程序可以使用WH_S HELLHook去接收重要的通知。
当外壳应用程序是激活的并且当顶层窗口建立或者销毁时,系统调用WH_SHELLHook子程。
WH_SHELL共有5钟情況:1 .只要有个top-1 evel> unown ed窗口被产生、起作用、或是被摧毁;2.当Taskbar需要重画某个按钮;3 .当系统需要显示关于Taskbar的一个程序的最小化形式;4 •当目前的键盘布局状态改变;5.当使用者按CtrlEsc去执行TaskMan ager (或相同级别的程序)。
按照惯例,外壳应用程序都不接收WH_SHELL消息。
所以,在应用程序能够接收WH_SH ELL消息之前,应用程序必须调用Syst emParamete rslnfofunc tion 注册它自己。
以上是13种常用的hook类型!二.按使用范围分类,主要有线程钩子和系统钩子(1)线程钩子监视指定线程的事件消息。
(2)系统钩子监视系统中的所有线程的事件消息。
因为系统钩子会影响系统中所有的应用程序,所以钩子函数必须放在独立的动态链接库(DLL)本篇论文是由为您在网络上收集整理的,论文版权属原作者,请不要用于商业用途或者抄袭,仅供参考学习之用,否则后果自负,如果此文侵犯您的合法权益,烦请联系我们。
中。
这是系统钩子和线程钩子很大的不同之处。
几点需要说明的地方:(1)如果对于同一事件(如鼠标消息)既安装了线程钩子又安装了系统钩子,那么系统会自动先调用线程钩子, 然后调用系统钩子。
(2)对同一事件消息可安装多个钩子处理过程,这些钩子处理过程形成了钩子链。
当前钩子处理结束后应把钩子信息传递给下一个钩子函数。
而且最近安装的钩子放在链的开始,而最早安装的钩子放在最后,也就是后加入的先获得控制权。
(3 )钩子特别是系统钩子会消耗消息处理时间,降低系统性能。
只有在必要的时候才安装钩子,在使用完毕后要及时卸载。
编写钩子程序编写钩子程序的步骤分为三步:定义钩子函数、安装钩子和卸载钩子。
1.定义钩子函数钩子函数是一种特殊的回调函数。
钩子监视的特定事件发生后,系统会调用钩子函数进行处理。
不同事件的钩子函数的形式是各不相同的。
下面以鼠标钩子函数举例说明钩子函数的原型:LRES ULTCALLBAC KHookProc(intnCode, W PARAMwPara m,LP ARAM IP aram)参数w Param和IPar am包含所钩消息的信息,比如鼠标位置、状态,键盘按键等。
nC ode包含有关消息本身的信息,比如是否从消息队列中移出。
我们先在钩子函数中实现自定义的功能,然后调用函数CallNextHookEx.把钩子信息传递给钩子链的下一个钩子函数。
C allNextHoo kEx.的原型如下:LRESULTC allNextHoo kEx(HHOOKh hk, intnCode, WPARAMwP aram, LPARA MIParam)参数hhk是钩子句柄。
nCode、wPa ram和1 Param是钩子函数。
当然也可以通过直接返回T RUE来丢弃该消息,就阻止了该消息的传递。
2.安装钩子在程序初始化的时候,调用函数SetWind owsHookEx安装钩子。
其函数原型为:HHOOKSe tWindowsHo okEx (intid Hook, HOOKP ROClpfn, IN STANCEhMod , DWORDdwTh readld)参数idHook表示钩子类型,它是和钩子函数类型一一对应的。
比如,WH KEYBO ARD表示安装的是键盘钩子,WH_MOU SE表不是鼠标钩子等等。
Lpfn是钩子函数的地址。
HMo d是钩子函数所在的实例的句柄。
对于线程钩子,该参数为NULL ;对于系统钩子,该参数为钩子函数所在的DLL句柄。
dwT hreadld指定钩子所监视的线程的线程号。
对于全局钩子,该参数为NULLoSetWindows HookEx返回所安装的钩子句柄。
3.卸载钩子当不再使用钩子时,必须及时卸载。
简单地调用函数BO OLUnhookWi ndowsHookE x (HHOOKhhk )艮卩可。