Python 3.9+实现Windows系统禁用键鼠的问题求助
解决Windows Server下Python UI自动化时冻结键鼠及打包问题
一、修复BlockInput的打包问题
你的ctypes代码无法打包,大概率是因为对user32.dll的引用方式不够明确,以及打包时缺少必要配置。按以下步骤修改:
- 修正代码写法
明确指定加载user32.dll,并添加权限检查和错误处理:
import ctypes from ctypes import wintypes # 加载user32.dll并指定函数原型 user32 = ctypes.WinDLL('user32', use_last_error=True) BlockInput = user32.BlockInput BlockInput.argtypes = [wintypes.BOOL] BlockInput.restype = wintypes.BOOL def block_input(block: bool) -> bool: # BlockInput需要管理员权限 result = BlockInput(block) if not result: error_code = ctypes.get_last_error() print(f"操作失败,错误码: {error_code}") return False return True # 使用示例 # block_input(True) # 冻结键鼠 # ... 执行自动化任务 ... # block_input(False) # 恢复键鼠
- 打包时的配置调整
使用auto-py-to-exe时注意:
- 勾选One File模式时,添加
--hidden-import ctypes到额外参数中 - 打包完成后,必须以管理员身份运行生成的exe(
BlockInputAPI需要管理员权限才能生效)
二、替代方案:通过低级钩子拦截键鼠输入
如果BlockInput仍有问题,可以用Windows低级钩子实现更精细的输入拦截,兼容Python3.9+且可正常打包:
import ctypes import ctypes.wintypes as wintypes import threading # 定义钩子回调类型 HOOKPROC = ctypes.CFUNCTYPE(wintypes.LRESULT, wintypes.int, wintypes.WPARAM, wintypes.LPARAM) user32 = ctypes.WinDLL('user32', use_last_error=True) kernel32 = ctypes.WinDLL('kernel32', use_last_error=True) # 钩子相关函数原型 user32.SetWindowsHookExA.argtypes = [wintypes.int, HOOKPROC, wintypes.HINSTANCE, wintypes.DWORD] user32.SetWindowsHookExA.restype = wintypes.HHOOK user32.CallNextHookEx.argtypes = [wintypes.HHOOK, wintypes.int, wintypes.WPARAM, wintypes.LPARAM] user32.CallNextHookEx.restype = wintypes.LRESULT user32.UnhookWindowsHookEx.argtypes = [wintypes.HHOOK] user32.UnhookWindowsHookEx.restype = wintypes.BOOL user32.GetMessageA.argtypes = [wintypes.LPMSG, wintypes.HWND, wintypes.UINT, wintypes.UINT] user32.GetMessageA.restype = wintypes.BOOL # 全局钩子句柄 mouse_hook = None keyboard_hook = None def mouse_hook_proc(nCode, wParam, lParam): # 拦截所有鼠标事件 if nCode >= 0: return 1 # 返回1表示拦截事件 return user32.CallNextHookEx(mouse_hook, nCode, wParam, lParam) def keyboard_hook_proc(nCode, wParam, lParam): # 拦截所有键盘事件 if nCode >= 0: return 1 # 返回1表示拦截事件 return user32.CallNextHookEx(keyboard_hook, nCode, wParam, lParam) def start_blocking(): global mouse_hook, keyboard_hook # 设置鼠标钩子(WH_MOUSE_LL = 14) mouse_hook = user32.SetWindowsHookExA(14, HOOKPROC(mouse_hook_proc), kernel32.GetModuleHandleA(None), 0) # 设置键盘钩子(WH_KEYBOARD_LL = 13) keyboard_hook = user32.SetWindowsHookExA(13, HOOKPROC(keyboard_hook_proc), kernel32.GetModuleHandleA(None), 0) # 启动消息循环维持钩子 msg = wintypes.MSG() while user32.GetMessageA(ctypes.byref(msg), None, 0, 0) != 0: user32.TranslateMessage(ctypes.byref(msg)) user32.DispatchMessage(ctypes.byref(msg)) def stop_blocking(): global mouse_hook, keyboard_hook if mouse_hook: user32.UnhookWindowsHookEx(mouse_hook) if keyboard_hook: user32.UnhookWindowsHookEx(keyboard_hook) # 使用示例 # 启动拦截线程 block_thread = threading.Thread(target=start_blocking, daemon=True) block_thread.start() # ... 执行自动化任务 ... # 停止拦截 stop_blocking()
这个方案不需要管理员权限(低级全局钩子无需权限),打包时同样建议添加--hidden-import ctypes参数。
注意事项
- 无论用哪种方案,自动化任务执行完毕后必须恢复键鼠输入,避免系统无法操作
- Windows Server环境下,确保程序运行时没有被系统安全软件拦截
- 若使用低级钩子,消息循环必须在单独线程中运行,避免阻塞自动化任务的主线程
内容的提问来源于stack exchange,提问作者Jimbo
相关产品推荐
相关产品推荐

