微信 4.x · Windows UI Automation

wx4auto

把微信桌面客户端变成可编程的

面向微信 4.x 的 UIA 自动化库。默认后台运行,不抢鼠标键盘,微信最小化也能收发。读消息走本地数据库,全量与毫秒级。

前提

微信 4.1 会把 UIA 控件树藏起来

从 4.1 起,微信在 GPU 合成渲染下主窗口会退化成一个纯画布,UIA 读不到任何子控件 —— 任何基于 UIA 的方案都受这条约束,与用不用本库无关。而且同一个窗口句柄会在「完整控件树」和「0 个子节点」之间来回切换。

  • 实测 4.1.8.107 控件树完整,4.1.15.13 只剩 2 个节点
  • 最常见的触发原因是微信自动更新把版本顶掉
  • 判断版本别文件大小或时间戳 —— 更新器会保留归档时间戳
  • 库的做法:每次操作前体检,树不在就明确报错,绝不静默失败

想长期稳定:锁版本 + 关掉微信自动更新。详见文档「环境与版本」。

实测数据

几个真实的数字

以下均为真机实测记录,不是理论值。

0.01秒

原生 FindAll 查找

同样的查找,Python 逐层遍历要 6.1 秒

3160条

通讯录读取

走数据库;控件树只能读到渲染出的十几行

100条

会话列表

走数据库;控件树路线只有十几条

15个

MCP 工具

8 个只读 + 7 个写,默认只读

105个

官方表情名

另带 30+ 条口语别名,按含义匹配

0次

鼠标位移

默认后台模式,点击输入发送全走 UIA 与 PostMessage

能力

它解决的实际问题

01

免前台 / 免鼠标

默认即后台模式。点击、输入、回车走 UIA 模式与 PostMessage,不抢前台、不移动鼠标,微信最小化时照样收发。

所有输入收口在一层里,降级路径会先校验目标窗口是不是当前前台,所以「绝不把按键发给别的程序」是结构性保证。

02

两条独立的数据通道

读操作优先走本地数据库(毫秒级、全量历史、群消息直接给出发送者),不满足条件时自动退回控件树。

出厂 auto:能用库就走库,不能就退回 UIA。写操作必须走控件树 —— 微信的设计如此。

03

窗口自己叫回来

窗口最小化或被收进托盘后,Qt 会卸载 UIA Provider,之后所有接口不报错但全是空结果。

库会自动发现并恢复:最小化走还原,收进托盘走微信自己的托盘逻辑(点托盘图标,不动鼠标,约 2 秒恢复)。不抢回你的前台焦点。

04

消息监听不漏不错

按数据库 sort_seq 水位做增量,与界面渲染无关,虚拟列表回收控件也不会漏。

水位落盘,重启续跑不重复推送。群消息也能拿到发送人 —— 这是控件树路线做不到的(微信把群昵称画在画布上)。

05

MCP 服务,给 agent 用

一条命令起 MCP 服务,接 Claude Desktop / Cursor 或任何兼容客户端,让 agent 直接操作微信。

默认只读:7 个写工具要显式开启才出现在工具列表里。默认只监听本机;绑非本机地址时强制要求令牌。

06

发送前校验

微信偶尔会吞字符或残留上一次输入,直接回车就可能发错内容。

输入后读回编辑框实际内容,做带长度惩罚的相似度比对,达到阈值才回车;不达标返回失败,而不是赌一把。

用法

代码形态

安装:pip install -e .

发消息与读消息

from wx4auto import WeChat

wx = WeChat()                       # 连上已登录的微信主窗口

wx.SendMsg("你好", who="张三")
wx.SendMsg("看这个", who="工作群", at=["李四"])
wx.SendFiles(r"C:\tmp\报告.pdf", who="张三")

for msg in wx.GetAllMessage():
    print(msg.type, msg.attr, msg.sender, msg.content)

监听并自动回复

def on_msg(msg, chat):
    if msg.type == "text" and "在吗" in msg.content:
        chat.SendMsg("在的")

wx.AddListenChat("客服群", on_msg)
wx.StartListening()                 # ← 只登记不启动,不会开始轮询
wx.KeepRunning()

给 agent 用(MCP)

# 默认只读;确认需要写操作再加 --allow-write
python -m wx4auto mcp --list-tools
边界

做不到和刻意不做的事

这些是实测后的结论,不是「以后再说」。

发语音条

未实现

微信没有上传语音文件入口,语音条只能现场录,需要虚拟声卡配合。接口保留并返回明确失败。

撤回 / 引用 / 转发

受阻塞

依赖消息右键菜单,该菜单在后台模式下弹不出来。三种方式都试过,目前明确失败而非假装成功。

红包 / 转账

刻意不做

涉及金钱,与自动化工具的能力边界无关。

协议层能力

刻意不做

不注入进程、不改内存、不碰网络协议、不做验证码或风控绕过。

操作别的机器上的微信

做不到

UIA 驱动的是本机微信,读数据库靠扫本机进程内存取密钥。服务在哪台机器,操作的就是哪台的微信。

Nuitka 编译提速

实测更慢

热点只是薄包装,真干活的是 C 实现与 COM 往返。真正的提速来自原生 FindAll 的算法修复。

下一步

从快速开始读起

四步跑通:装依赖、体检控件树、连上窗口、发一条消息。