You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python 3.9+实现Windows系统禁用键鼠的问题求助

解决Windows Server下Python UI自动化时冻结键鼠及打包问题

一、修复BlockInput的打包问题

你的ctypes代码无法打包,大概率是因为对user32.dll的引用方式不够明确,以及打包时缺少必要配置。按以下步骤修改:

  1. 修正代码写法
    明确指定加载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) # 恢复键鼠
  1. 打包时的配置调整
    使用auto-py-to-exe时注意:
  • 勾选One File模式时,添加--hidden-import ctypes到额外参数中
  • 打包完成后,必须以管理员身份运行生成的exe(BlockInput API需要管理员权限才能生效)

二、替代方案:通过低级钩子拦截键鼠输入

如果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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 00:25:51