SetWindowsHookExW返回0且无错误:HID鼠标钩子拦截问题求助
解决SetWindowsHookExW返回0且错误126的问题
问题原因分析
你遇到的[WinError 126] 找不到指定的模块错误,核心原因是SetWindowsHookExW的第三个参数(模块句柄)的获取方式存在问题,同时代码缺少低级别鼠标钩子必需的消息循环——即使钩子设置成功,没有消息循环也无法触发回调函数。
另外,原代码没有为SetWindowsHookExW开启use_last_error=True,导致GetLastError()返回的错误码被后续ctypes调用覆盖,出现返回0的异常情况。
修正后的代码
import ctypes from ctypes import wintypes import win32api import win32con # 定义钩子回调函数类型 HOOKPROC = ctypes.WINFUNCTYPE(ctypes.c_int, ctypes.c_int, wintypes.WPARAM, wintypes.LPARAM) # 鼠标钩子回调函数 def low_level_mouse_proc(nCode, wParam, lParam): if nCode >= 0: # 拦截左键按下和抬起事件 if wParam == win32con.WM_LBUTTONDOWN: print("左键按下已拦截") return 1 # 返回1阻止默认事件 if wParam == win32con.WM_LBUTTONUP: print("左键抬起已拦截") return 1 # 返回1阻止默认事件 # 传递未拦截的事件给下一个钩子 return ctypes.windll.user32.CallNextHookEx(None, nCode, wParam, lParam) # 转换Python函数为C回调 low_level_mouse_proc_c = HOOKPROC(low_level_mouse_proc) def set_mouse_hook(): WH_MOUSE_LL = 14 # 获取当前进程的模块句柄(python.exe) kernel32 = ctypes.WinDLL('kernel32', use_last_error=True) module_handle = kernel32.GetModuleHandleW(None) # 正确配置SetWindowsHookExW,开启use_last_error user32 = ctypes.WinDLL('user32', use_last_error=True) mouse_hook = user32.SetWindowsHookExW( WH_MOUSE_LL, low_level_mouse_proc_c, module_handle, 0 ) if not mouse_hook: print(f"钩子设置失败: {ctypes.WinError(ctypes.get_last_error())}") return None print("鼠标钩子已成功设置") return mouse_hook def main(): hook = set_mouse_hook() if not hook: return # 启动消息循环,低级别钩子依赖此循环分发事件 msg = wintypes.MSG() user32 = ctypes.WinDLL('user32') while user32.GetMessageW(ctypes.byref(msg), None, 0, 0) != 0: user32.TranslateMessage(ctypes.byref(msg)) user32.DispatchMessageW(ctypes.byref(msg)) # 卸载钩子(程序退出时执行) ctypes.windll.user32.UnhookWindowsHookEx(hook) if __name__ == "__main__": main()
关键修正点
- 模块句柄获取:明确使用
kernel32.GetModuleHandleW(None)获取当前进程的可执行文件句柄,确保系统能找到钩子函数所在的模块。 - 错误码处理:为
kernel32和user32的WinDLL实例开启use_last_error=True,并通过ctypes.get_last_error()获取准确的错误码,避免错误被覆盖。 - 添加消息循环:低级别全局钩子(如WH_MOUSE_LL)需要调用进程运行消息循环,才能接收和处理钩子事件,否则回调函数永远不会被触发。
- 保留回调引用:将转换后的C回调函数
low_level_mouse_proc_c设为全局变量,防止Python垃圾回收机制回收该函数,导致钩子失效。
额外注意事项
- 确保你的Python版本与系统位数一致(64位Python对应64位Windows),否则可能出现模块加载失败的问题。
- 低级别鼠标钩子不需要管理员权限即可正常工作。
- 测试时建议直接运行Python脚本文件,避免在部分IDE控制台中运行(可能影响消息循环正常执行)。
内容的提问来源于stack exchange,提问作者CodingCode
相关产品推荐
相关产品推荐

