SetWindowsHookExA 函数 (winuser.h)

将应用程序定义的挂钩过程安装到挂钩链中。 你将安装挂钩过程来监视系统的某些类型的事件。 这些事件与特定线程或与调用线程位于同一桌面中的所有线程相关联。

语法

HHOOK SetWindowsHookExA(
  [in] int       idHook,
  [in] HOOKPROC  lpfn,
  [in] HINSTANCE hmod,
  [in] DWORD     dwThreadId
);

参数

[in] idHook

类型: int

要安装的挂钩过程的类型。 此参数的取值可为下列值之一:

含义
WH_CALLWNDPROC
4

安装一个挂钩过程,用于在系统将消息发送到目标窗口过程之前监视消息。 有关详细信息,请参阅 CallWndProc 挂钩过程。

WH_CALLWNDPROCRET
12
安装一个挂钩过程,该过程在目标窗口过程处理消息后监视消息。 有关详细信息,请参阅 [HOOKPROC 回调函数] (nc-winuser-hookproc.md) 挂钩过程。
WH_CBT
5
安装用于接收对 CBT 应用程序有用的通知的挂钩过程。 有关详细信息,请参阅 CBTProc 挂钩过程。
WH_DEBUG
9

安装可用于调试其他挂钩过程的挂钩过程。 有关详细信息,请参阅 DebugProc 挂钩过程。

WH_FOREGROUNDIDLE
11

安装将在应用程序的前台线程变为空闲状态时调用的挂钩过程。 此挂钩可用于在空闲时间执行低优先级任务。 有关详细信息,请参阅 ForegroundIdleProc 挂钩过程。

WH_GETMESSAGE
3

安装用于监视发布到消息队列的消息的挂钩过程。 有关详细信息,请参阅 GetMsgProc 挂钩过程。

WH_JOURNALPLAYBACK
1

警告

Windows 11及更新版本:不支持日记挂钩 API。 建议改用 SendInput TextInput API。

安装一个挂钩过程,该过程发布以前由 WH_JOURNALRECORD 挂钩过程记录的消息。 有关详细信息,请参阅 JournalPlaybackProc 挂钩过程。

WH_JOURNALRECORD
0

警告

Windows 11及更新版本:不支持日记挂钩 API。 建议改用 SendInput TextInput API。

安装一个挂钩过程,用于记录发布到系统消息队列的输入消息。 此挂钩可用于记录宏。 有关详细信息,请参阅 JournalRecordProc 挂钩过程。

WH_KEYBOARD
2

安装用于监视击键消息的挂钩过程。 有关详细信息,请参阅 KeyboardProc 挂钩过程。

WH_KEYBOARD_LL
13
安装用于监视低级别键盘输入事件的挂钩过程。 有关详细信息,请参阅 [LowLevelKeyboardProc] (/windows/win32/winmsg/lowlevelkeyboardproc) 挂钩过程。
WH_MOUSE
7

安装监视鼠标消息的挂钩过程。 有关详细信息,请参阅 MouseProc 挂钩过程。

WH_MOUSE_LL
14

安装用于监视低级别鼠标输入事件的挂钩过程。 有关详细信息,请参阅 LowLevelMouseProc 挂钩过程。

WH_MSGFILTER
-1

安装挂钩过程,用于监视由于对话框、消息框、菜单或滚动条中的输入事件而生成的消息。 有关详细信息,请参阅 MessageProc 挂钩过程。

WH_SHELL
10
安装一个挂钩过程,用于接收对 shell 应用程序有用的通知。 有关详细信息,请参阅 ShellProc 挂钩过程。
WH_SYSMSGFILTER
6

安装挂钩过程,用于监视由于对话框、消息框、菜单或滚动条中的输入事件而生成的消息。 挂钩过程监视与调用线程位于同一桌面中的所有应用程序的消息。 有关详细信息,请参阅 SysMsgProc 挂钩过程。

[in] lpfn

类型: HOOKPROC

指向挂钩过程的指针。 如果 dwThreadId 参数为零或指定由其他进程创建的线程的标识符, 则 lpfn 参数必须指向 DLL 中的挂钩过程。 否则, lpfn 可以指向与当前进程关联的代码中的挂钩过程。

[in] hmod

类型: HINSTANCE

DLL 的句柄,其中包含 lpfn 参数指向的挂钩过程。 如果 dwThreadId 参数指定当前进程创建的线程,并且挂钩过程位于与当前进程关联的代码中,则必须将 hMod 参数设置为 NULL

[in] dwThreadId

类型:DWORD

要与挂钩过程关联的线程的标识符。 对于桌面应用,如果此参数为零,则挂钩过程与调用线程在同一桌面中运行的所有现有线程相关联。 对于 Windows 应用商店应用,请参阅“备注”部分。

返回值

类型: HHOOK

如果函数成功,则返回值是挂钩过程的句柄。

如果函数失败,则返回值为 NULL。 要获得更多的错误信息,请调用 GetLastError。

注解

SetWindowsHookEx 可用于将 DLL 注入另一个进程。 32 位 DLL 无法注入 64 位进程,64 位 DLL 无法注入 32 位进程。 如果应用程序需要在其他进程中使用挂钩,则要求 32 位应用程序调用 SetWindowsHookEx 以将 32 位 DLL 注入到 32 位进程中,64 位应用程序调用 SetWindowsHookEx 以将 64 位 DLL 注入 64 位进程。 32 位和 64 位 DLL 必须具有不同的名称。

由于挂钩在应用程序的上下文中运行,因此它们必须与应用程序的“位性”匹配。 如果 32 位应用程序在 64 位 Windows 上安装全局挂钩,则会将 32 位挂钩注入每个 32 位进程, (通常的安全边界) 应用。 在 64 位进程中,线程仍标记为“已挂钩”。但是,由于 32 位应用程序必须运行挂钩代码,因此系统会在挂钩应用的上下文中执行挂钩;具体而言,在调用 SetWindowsHookEx 的线程上。 这意味着挂钩应用程序必须继续泵送消息,否则可能会阻止 64 位进程的正常运行。

如果 64 位应用程序在 64 位 Windows 上安装全局挂钩,则会将 64 位挂钩注入每个 64 位进程,而所有 32 位进程都使用对挂钩应用程序的回调。

若要挂接 64 位 Windows 安装桌面上的所有应用程序,请从适当的进程安装 32 位全局挂钩和 64 位全局挂钩,并确保在挂钩应用程序中保留抽送消息,以避免阻止正常运行。 如果已有一个 32 位全局挂钩应用程序,并且它不需要在每个应用程序的上下文中运行,则可能不需要创建 64 位版本。

如果 hMod 参数为 NULLdwThreadId 参数为零或指定由另一个进程创建的线程的标识符,则可能会出现错误。

调用 CallNextHookEx 函数 以链接到下一个挂钩过程是可选的,但强烈建议这样做:否则,安装了挂钩的其他应用程序将不会收到挂钩通知,因此行为可能不正确。 除非绝对需要阻止其他应用程序看到通知,否则应调用 CallNextHookEx

在终止之前,应用程序必须调用 UnhookWindowsHookEx 函数 来释放与挂钩关联的系统资源。

挂钩的范围取决于挂钩类型。 某些挂钩只能设置全局范围;也可以仅为特定线程设置其他线程,如下表所示。

挂钩 范围
WH_CALLWNDPROC 线程或全局
WH_CALLWNDPROCRET 线程或全局
WH_CBT 线程或全局
WH_DEBUG 线程或全局
WH_FOREGROUNDIDLE 线程或全局
WH_GETMESSAGE 线程或全局
WH_JOURNALPLAYBACK 仅限全局
WH_JOURNALRECORD 仅限全局
WH_KEYBOARD 线程或全局
WH_KEYBOARD_LL 仅限全局
WH_MOUSE 线程或全局
WH_MOUSE_LL 仅限全局
WH_MSGFILTER 线程或全局
WH_SHELL 线程或全局
WH_SYSMSGFILTER 仅限全局

对于指定的挂钩类型,首先调用线程挂钩,然后调用全局挂钩。 请注意,可以在安装挂钩的线程上调用WH_MOUSE、WH_KEYBOARD、WH_JOURNAL*、WH_SHELL和低级别挂钩,而不是在处理挂钩的线程上调用。 对于这些挂钩,如果 32 位挂钩在挂钩链中的 64 位挂钩之前,可能会同时调用 32 位和 64 位挂钩。

全局挂钩是共享资源,安装挂钩会影响调用线程所在的同一桌面中的所有应用程序。 所有全局挂钩函数都必须在库中。 全局挂钩应限制为特殊用途应用程序,或在应用程序调试期间用作辅助开发工具。 不再需要挂钩的库应删除其挂钩过程。

Windows 应用商店应用开发如果 dwThreadId 为零,则 Windows 应用商店应用进程和 Windows 运行时 代理进程不会在进程内加载窗口挂钩 DLL,除非它们由任一 UIAccess 进程 (辅助功能工具) 安装。 通知在安装程序的线程上针对以下挂钩传递:

  • WH_JOURNALPLAYBACK
  • WH_JOURNALRECORD
  • WH_KEYBOARD
  • WH_KEYBOARD_LL
  • WH_MOUSE
  • WH_MOUSE_LL
此行为类似于挂钩 DLL 与目标应用程序进程之间存在体系结构不匹配的情况,例如,当挂钩 DLL 为 32 位且应用程序进程为 64 位时发生的情况。

示例

有关示例,请参阅 安装和释放挂钩过程

注意

winuser.h 标头将 SetWindowsHookEx 定义为别名,该别名根据 UNICODE 预处理器常量的定义自动选择此函数的 ANSI 或 Unicode 版本。 将非特定编码别名的使用与非非特定编码的代码混合使用可能会导致不匹配,从而导致编译或运行时错误。 有关详细信息,请参阅 函数原型的约定

要求

要求
最低受支持的客户端 Windows 2000 Professional [仅限桌面应用]
最低受支持的服务器 Windows 2000 Server [仅限桌面应用]
目标平台 Windows
标头 winuser.h (包括 Windows.h)
Library User32.lib
DLL User32.dll
API 集 在 Windows 8) 中引入的 ext-ms-win-ntuser-window-l1-1-0 (

另请参阅

CallNextHookEx 函数

CallWindowProc 函数

UnhookWindowsHookEx 函数

CBTProc

CallWndProc

CallWndRetProc

DebugProc

ForegroundIdleProc

GetMsgProc

JournalPlaybackProc

JournalRecordProc

KeyboardProc

LowLevelKeyboardProc

LowLevelMouseProc

MessageProc

MouseProc

ShellProc

SysMsgProc

概念性

挂钩