微信 4.1 会把 UIA 控件树藏起来
从 4.1 起,微信在 GPU 合成渲染下主窗口会退化成一个纯画布,UIA 读不到任何子控件 —— 任何基于 UIA 的方案都受这条约束,与用不用本库无关。而且同一个窗口句柄会在「完整控件树」和「0 个子节点」之间来回切换。
- 实测 4.1.8.107 控件树完整,4.1.15.13 只剩 2 个节点
- 最常见的触发原因是微信自动更新把版本顶掉
- 判断版本别文件大小或时间戳 —— 更新器会保留归档时间戳
- 库的做法:每次操作前体检,树不在就明确报错,绝不静默失败
想长期稳定:锁版本 + 关掉微信自动更新。详见文档「环境与版本」。
几个真实的数字
以下均为真机实测记录,不是理论值。
原生 FindAll 查找
同样的查找,Python 逐层遍历要 6.1 秒
通讯录读取
走数据库;控件树只能读到渲染出的十几行
会话列表
走数据库;控件树路线只有十几条
MCP 工具
8 个只读 + 7 个写,默认只读
官方表情名
另带 30+ 条口语别名,按含义匹配
鼠标位移
默认后台模式,点击输入发送全走 UIA 与 PostMessage
它解决的实际问题
免前台 / 免鼠标
默认即后台模式。点击、输入、回车走 UIA 模式与 PostMessage,不抢前台、不移动鼠标,微信最小化时照样收发。
所有输入收口在一层里,降级路径会先校验目标窗口是不是当前前台,所以「绝不把按键发给别的程序」是结构性保证。
两条独立的数据通道
读操作优先走本地数据库(毫秒级、全量历史、群消息直接给出发送者),不满足条件时自动退回控件树。
出厂 auto:能用库就走库,不能就退回 UIA。写操作必须走控件树 —— 微信的设计如此。
窗口自己叫回来
窗口最小化或被收进托盘后,Qt 会卸载 UIA Provider,之后所有接口不报错但全是空结果。
库会自动发现并恢复:最小化走还原,收进托盘走微信自己的托盘逻辑(点托盘图标,不动鼠标,约 2 秒恢复)。不抢回你的前台焦点。
消息监听不漏不错
按数据库 sort_seq 水位做增量,与界面渲染无关,虚拟列表回收控件也不会漏。
水位落盘,重启续跑不重复推送。群消息也能拿到发送人 —— 这是控件树路线做不到的(微信把群昵称画在画布上)。
MCP 服务,给 agent 用
一条命令起 MCP 服务,接 Claude Desktop / Cursor 或任何兼容客户端,让 agent 直接操作微信。
默认只读:7 个写工具要显式开启才出现在工具列表里。默认只监听本机;绑非本机地址时强制要求令牌。
发送前校验
微信偶尔会吞字符或残留上一次输入,直接回车就可能发错内容。
输入后读回编辑框实际内容,做带长度惩罚的相似度比对,达到阈值才回车;不达标返回失败,而不是赌一把。
代码形态
安装: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 的算法修复。
从快速开始读起
四步跑通:装依赖、体检控件树、连上窗口、发一条消息。