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

Windows服务中使用pynput无法检测鼠标移动的解决方案咨询

解决Windows服务中无法监控鼠标/键盘输入的问题

核心原因

Windows服务默认运行在Session 0(系统级非交互式会话),该会话没有访问用户桌面的权限,因此无法直接捕获用户操作的鼠标/键盘事件——这就是你的代码在控制台正常、转为服务后失效的根本原因。

可行实现方案

方案1:允许服务与桌面交互(不推荐,存在安全/兼容性问题)

这是最直接但风险较高的方法,仅适用于旧版Windows或测试场景:

  • 打开services.msc,找到你的服务并右键打开属性
  • 切换到「登录」选项卡,勾选「允许服务与桌面交互」
  • 重启服务

注意:Windows Vista及以上系统引入了Session 0隔离机制,该选项可能无法正常工作,且会带来安全隐患(服务可能被桌面进程攻击)。

方案2:拆分服务与桌面监控进程(推荐,简单可靠)

将程序拆分为两部分:后台服务负责核心逻辑,独立的桌面进程负责捕获鼠标/键盘事件,两者通过IPC(进程间通信)协作:

  1. 桌面监控进程:保留你原有的mouse.Listener逻辑,捕获事件后通过IPC给服务发送信号
  2. Windows服务:移除鼠标监控代码,改为监听IPC消息,收到信号后执行reset_timer
  3. 将桌面进程设置为用户登录时自动启动(可放入用户「启动」文件夹,或添加注册表项HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run)

示例代码片段

桌面监控进程:

import mouse
import win32pipe
import win32file

def send_reset_signal():
    # 连接到服务的命名管道
    try:
        pipe = win32file.CreateFile(
            r'\\.\pipe\MouseMonitorPipe',
            win32file.GENERIC_WRITE,
            0,
            None,
            win32file.OPEN_EXISTING,
            0,
            None
        )
        win32file.WriteFile(pipe, b'reset_timer')
        win32file.CloseHandle(pipe)
    except Exception:
        # 处理管道连接失败(如服务未启动)
        pass

def main():
    listener = mouse.Listener(
        on_move=send_reset_signal,
        on_click=send_reset_signal,
        on_scroll=send_reset_signal
    )
    listener.start()
    listener.join()

if __name__ == '__main__':
    main()

服务中的IPC监听逻辑:

import win32pipe
import win32file
import pywintypes
import threading

def reset_timer():
    # 你的定时器重置逻辑
    pass

def pipe_listener():
    pipe_name = r'\\.\pipe\MouseMonitorPipe'
    while True:
        try:
            # 创建命名管道
            pipe = win32pipe.CreateNamedPipe(
                pipe_name,
                win32pipe.PIPE_ACCESS_DUPLEX,
                win32pipe.PIPE_TYPE_MESSAGE | win32pipe.PIPE_READMODE_MESSAGE | win32pipe.PIPE_WAIT,
                1, 65536, 65536,
                0,
                None
            )
            win32pipe.ConnectNamedPipe(pipe, None)
            # 循环读取消息
            while True:
                result, data = win32file.ReadFile(pipe, 4096)
                if data == b'reset_timer':
                    reset_timer()
            win32file.CloseHandle(pipe)
        except pywintypes.error:
            # 处理管道断开、连接异常等情况
            pass

# 在服务启动时启动监听线程
def service_start():
    threading.Thread(target=pipe_listener, daemon=True).start()

方案3:全局钩子DLL注入(复杂但原生)

如果需要完全由服务处理,可编写C/C++全局鼠标钩子DLL,注入到用户会话的进程(如explorer.exe)中捕获事件,再通过IPC将事件传递给服务。这种方法实现难度高,但能避免拆分进程的复杂度,适合对架构有严格要求的场景。

内容的提问来源于stack exchange,提问作者Maimun Ahmed

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 22:48:14