24 KiB
WxAgent C# 技术开发计划
版本:0.2
日期:2026-09-03
目标:使用 C# 独立实现 wxautox4 商业版的业务功能;只兼容功能,不兼容 Python API。第一阶段不实现 Windows Service 和正式控制面。
1. 结论
可以采用以下开发方式:
- Linux 作为主要开发、代码审查、构建和纯逻辑测试环境。
- Linux 交叉编译
win-x64发布包。 - Windows 真机运行 Desktop Agent,在已登录且未锁定的用户会话中连接微信并执行 UI Automation 验证。
- 当前项目的 Windows MCP 已能识别微信窗口及关键 UIA 节点,可作为第一台真机验证环境。
限制:
- Linux 只能编译 Windows UIA 代码,不能执行 FlaUI、COM、剪贴板、窗口和微信操作测试。
- Windows 真机必须保持用户登录、桌面可交互、微信已登录。
- 暂不使用 NativeAOT;普通 self-contained/single-file 发布可从 Linux 生成。安装包、代码签名和 UIA 真机测试放在 Windows 完成。
2. 范围
2.1 包含
- 微信进程、窗口和登录状态检测
- 会话列表、会话切换和子窗口
- 消息发送、读取、解析、监听和去重
- 文本、图片、文件、语音、链接等消息类型
- 联系人、好友申请和好友信息
- 群聊创建、成员和群信息管理
- 历史消息、附件下载、OCR、语音转文字
- 朋友圈读取、发布、点赞和评论
- 本地 Desktop Agent、CLI、日志和诊断工具
- 只读扫描
Weixin.exe内存,校验 SQLCipher 密钥并读取本地微信数据库 - 面向未来 Web/UI 控制面的应用层 API
2.2 暂不包含
- Windows Service
- 正式 Web UI 或桌面 UI
- SaaS、多租户和远程集群控制
- 商业授权、计费和自动升级
- 绕过登录、验证码、风控或平台限制
- 微信协议、数据库写入、DLL 注入或进程内存修改
只读数据库例外严格限定为:以最小进程权限读取 Weixin.exe 内存中的 WCDB 候选密钥,以目标数据库 page 1 HMAC-SHA512 验证后,使用 SQLCipher 4 只读连接查询本机数据库。禁止输出未验证候选、记录完整密钥、修改数据库或将该能力扩展为协议/登录绕过。
3. 最小项目结构
第一阶段使用以下结构,不提前拆分微服务:
WxAgent.sln
├── src/
│ ├── WxAgent.Core/ # net8.0,模型、解析、去重、状态机、业务用例
│ ├── WxAgent.Windows/ # net8.0-windows,FlaUI/UIA/Win32 实现
│ └── WxAgent.Host/ # net8.0-windows,Desktop Agent 和 CLI
└── tests/
└── WxAgent.Core.Tests/ # net8.0,可在 Linux 执行
开始真机自动化后再增加:
tests/WxAgent.Windows.Tests/ # 仅在 Windows 真机执行
这种拆分的目的不是建立通用插件框架,而是让纯业务逻辑能够在 Linux 运行测试,同时隔离 Windows 专用引用。
4. 技术选型
| 能力 | 选型 | 说明 |
|---|---|---|
| Runtime | .NET 8 LTS,后续可升级 .NET 10 | 优先使用成熟工具链 |
| UI Automation | FlaUI.UIA3 | 首选封装,缺失能力再直接调用 UIA COM |
| Win32 | Microsoft.Windows.CsWin32 | 按需生成 P/Invoke,不手写大批声明 |
| 并发 | Channel<T>、Task、IAsyncEnumerable<T> |
所有 UI 写操作进入单队列 |
| 配置 | Microsoft.Extensions.Configuration |
JSON + 环境变量 |
| 日志 | Microsoft.Extensions.Logging |
暂不额外引入日志框架 |
| 序列化 | System.Text.Json |
UI 快照、命令和事件 |
| 持久化 | SQLite | 仅保存消息游标、短期去重和任务状态 |
| 微信数据库只读 | Microsoft.Data.Sqlite.Core + SQLCipher bundle | raw key、只读模式、query_only,不写库 |
| 测试 | xUnit | Linux 纯逻辑测试 + Windows 真机测试 |
| 发布 | self-contained win-x64 |
第一阶段只支持 Windows x64 |
除非验证证明 FlaUI 无法满足需求,否则不要从零封装完整 UI Automation COM API。
5. Linux 编译、Windows 验证方案
5.1 Windows 项目配置
WxAgent.Windows.csproj 和 WxAgent.Host.csproj 使用:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0-windows10.0.19041.0</TargetFramework>
<EnableWindowsTargeting>true</EnableWindowsTargeting>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<PlatformTarget>x64</PlatformTarget>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<PublishTrimmed>false</PublishTrimmed>
</PropertyGroup>
</Project>
EnableWindowsTargeting 允许 Linux/macOS 恢复和编译 Windows Targeting Pack。PublishTrimmed 暂时关闭,避免 FlaUI、COM 或反射代码被错误裁剪。
5.2 Linux 构建命令
dotnet restore WxAgent.sln -p:EnableWindowsTargeting=true
dotnet test tests/WxAgent.Core.Tests -c Release
dotnet build WxAgent.sln -c Release -p:EnableWindowsTargeting=true
dotnet publish src/WxAgent.Host \
-c Release \
-r win-x64 \
--self-contained true \
-p:EnableWindowsTargeting=true \
-p:PublishSingleFile=true \
-p:PublishTrimmed=false
发布产物:
src/WxAgent.Host/bin/Release/net8.0-windows10.0.19041.0/win-x64/publish/
5.3 Windows 真机验证流程
Linux build/test/publish
↓
复制 publish 目录到 Windows
↓
Windows 用户登录并启动微信
↓
运行 WxAgent.Host doctor
↓
运行 smoke 测试
↓
保存 UI 树、日志和测试报告
优先通过 Windows MCP 操作和检查微信;MCP 不足时,再通过 SSH/PowerShell 上传、启动和收集结果。
建议 CLI:
WxAgent.Host doctor
WxAgent.Host inspect-ui --output artifacts/ui-tree.json
WxAgent.Host status
WxAgent.Host conversations
WxAgent.Host open-chat "文件传输助手"
WxAgent.Host send-text "文件传输助手" "wxagent smoke test"
WxAgent.Host messages --visible
WxAgent.Host listen --seconds 60
WxAgent.Host smoke
5.4 自动化边界
- Linux CI:编译全部项目,执行
WxAgent.Core.Tests。 - Windows 真机:执行
WxAgent.Windows.Tests和 smoke/endurance 测试。 - 安装包、签名、FlaUI/UIA 执行、剪贴板和截图只能在 Windows 验证。
- 微信操作不能在 Windows Service 的 Session 0 中运行。
6. 当前真机 UIA 基线
2026-09-03 已通过 Windows MCP 对当前微信窗口进行 UI Automation 检查。已确认以下节点可见:
| 区域 | ControlType | AutomationId/名称 |
|---|---|---|
| 主视图 | Group | MainView |
| 左侧导航 | ToolBar | MainView.main_tabbar |
| 会话列表 | List | session_list |
| 会话项 | ListItem | session_item_{会话名称} |
| 聊天页面 | Group | chat_message_page |
| 消息列表 | List | chat_message_list |
| 消息项 | ListItem | chat_message_list.qt_scrollarea_viewport.chat_bubble_item_view |
| 输入框 | Edit | chat_input_field |
| 输入区工具栏 | ToolBar | tool_bar_accessible |
| 当前会话标题 | Text | 路径末端 current_chat_name_label |
| 发送按钮 | Button | 名称 发送 |
| 发送文件按钮 | Button | 名称 发送文件 |
| 朋友圈入口 | Button | 名称 朋友圈 |
| 通讯录入口 | Button | 名称 通讯录 |
| 更多入口 | Button | MainView.main_tabbar.tabbar_setting |
这份基线可以直接用于第一版定位器,不需要重新从桌面坐标开始摸索。AutomationId 不是微信公开稳定接口,必须保留 Name、ControlType、祖先节点和相对关系作为回退条件。
定位顺序统一为:
AutomationId
→ ControlType + Name
→ 稳定祖先节点 + 相对关系
→ UIA Pattern
→ 坐标兜底
禁止业务代码直接散落绝对坐标。确需坐标时集中登记,并记录适用 DPI、窗口尺寸和升级路径。
7. 功能参考对象
7.1 功能行为基线:wxautox4 公开文档
以下文档作为“实现什么”和“如何验收”的主要参考,不复制或反编译商业包实现:
行为复制原则:
- 依据公开文档建立功能矩阵。
- 使用测试账号观察输入、输出和错误场景。
- 独立设计 C# 模型和实现。
- 不反编译、不搬运商业包源码或受保护资源。
7.2 C#/UIA 实现参考
优先阅读顺序:
- wxautox4 的
WeChat、Chat、Message文档。 - FlaUI UIA3 示例。
- Microsoft UIA threading、tree、events、cache、virtualized items。
- 使用 FlaUInspect/Accessibility Insights 对照当前微信控件树。
8. 功能复制矩阵
8.1 WeChat 级能力
| wxautox4 公开能力 | C# 计划能力 | 主要实现位置 | 阶段 |
|---|---|---|---|
KeepRunning |
Desktop Agent 生命周期 | Host | M1 |
GetSession |
获取当前会话列表 | SessionReader | M2 |
ChatWith |
搜索并打开会话 | ChatNavigator | M2 |
GetSubWindow |
查找聊天子窗口 | WindowRegistry | M4 |
GetAllSubWindow |
枚举聊天子窗口 | WindowRegistry | M4 |
AddListenChat |
注册监听目标 | MessageMonitor | M3 |
RemoveListenChat |
移除监听目标 | MessageMonitor | M3 |
StartListening |
开始监听 | MessageMonitor | M3 |
StopListening |
停止监听 | MessageMonitor | M3 |
SwitchToChat |
切换聊天页面 | MainNavigator | M2 |
SwitchToContact |
切换通讯录 | MainNavigator | M4 |
Moments |
进入朋友圈 | MomentsNavigator | M5 |
PublishMoment |
发布朋友圈 | MomentsClient | M5 |
GetNewFriends |
获取好友申请 | ContactClient | M4 |
AddNewFriend |
添加好友 | ContactClient | M4 |
EditFriendInfo |
修改备注等信息 | ContactClient | M4 |
GetNextNewMessage |
获取下一个新消息会话 | MessageMonitor | M3 |
GetAllRecentGroups |
最近群聊列表 | GroupClient | M4 |
SendUrlCard |
发送链接卡片 | MessageSender | M5 |
GetHistoryMessage |
获取历史消息 | HistoryReader | M4 |
GetFriendDetails |
好友列表及详情 | ContactClient | M4 |
CreateGroup |
创建群聊 | GroupClient | M4 |
IsOnline |
登录/在线状态 | WechatConnection | M1 |
GetMyInfo |
获取当前账号信息 | AccountReader | M4 |
GetDialog |
对话框识别与操作 | DialogHandler | M2 |
8.2 Chat 级能力
| wxautox4 公开能力 | C# 计划能力 | 阶段 |
|---|---|---|
Show |
激活聊天窗口 | M1 |
ChatInfo |
当前会话信息 | M2 |
AtAll |
群聊 @所有人 | M4 |
SendMsg |
文本、@、引用文本发送 | M2/M3 |
SendFiles |
图片和文件发送 | M2 |
SendAudio |
语音文件发送 | M5 |
GetAllMessage |
可见消息读取 | M2 |
AddGroupMembers |
添加群成员 | M4 |
SetGroupName |
修改群名称 | M4 |
SetGroupRemark |
修改群备注 | M4 |
SetGroupAnnouncement |
修改群公告 | M4 |
SetGroupMyNickname |
修改群昵称 | M4 |
Close |
关闭聊天窗口 | M2 |
8.3 Message 级能力
| 类别 | C# 计划能力 | 阶段 |
|---|---|---|
| 通用属性 | 会话、发送人、时间、方向、消息类型、原始 UI 节点摘要 | M2 |
roll_into_view |
虚拟化消息滚动到可见区域 | M3 |
click |
激活消息 | M3 |
select_option |
打开消息菜单并选择动作 | M3 |
quote |
引用回复 | M3 |
forward |
转发 | M4 |
tickle |
拍一拍 | M5 |
sender_info |
读取发送人信息 | M4 |
add_friend/delete_friend |
好友操作 | M4 |
download/save_files |
图片、文件、视频下载 | M4 |
ocr |
图片 OCR | M4 |
to_text |
语音转文字 | M4 |
get_url |
获取链接 URL | M5 |
get_content |
合并消息或特殊内容读取 | M5 |
to_markdown |
标准化内容输出 | M5 |
8.4 Session 和朋友圈
| wxautox4 公开能力 | C# 计划能力 | 阶段 |
|---|---|---|
Session search |
会话搜索 | M2 |
go_top/roll_up/roll_down |
会话列表滚动 | M2 |
click/double_click |
打开主窗口或子窗口 | M2/M4 |
delete/hide |
删除或隐藏会话 | M4 |
select_option |
会话上下文菜单 | M4 |
Moment GetMoments |
读取朋友圈 | M5 |
Refresh |
刷新朋友圈 | M5 |
Publish |
发布朋友圈 | M5 |
Like |
点赞 | M5 |
Comment |
评论 | M5 |
9. 核心设计
9.1 自动化命令队列
同一个微信窗口的写操作必须串行:
业务请求
→ Channel<AutomationCommand>
→ 专用 UIA 工作线程
→ 微信窗口
不要并行点击、输入或滚动同一个窗口。读取操作也应通过统一调度,避免读取过程中页面被另一个命令切换。
9.2 UIA 线程
- 在专用 Windows 线程初始化 UIA/COM。
- UIA 事件处理器只采集最小信息并快速返回。
- 不在 UIA 回调线程执行业务回调或耗时操作。
- UIA 元素引用可能失效;跨步骤保存 RuntimeId 或轻量快照,不长期持有元素对象。
9.3 消息监听
微信 4.x 消息列表存在虚拟化,监听采用:
UIA 事件
+ 低频轮询兜底
+ 可见消息快照比较
+ 有界滑动窗口去重
消息指纹建议:
会话标识 + 发送方向 + 发送人 + 消息类型 + 内容摘要 + 时间标记 + 邻近顺序
微信没有公开稳定消息 ID,因此指纹只能用于工程去重,不能作为永久业务主键。
9.4 操作重试
允许重试:
- 查找窗口和控件
- 页面状态等待
- 会话读取
- 消息读取
- 历史加载
禁止盲目重试:
- 发送消息或文件
- 添加/删除联系人
- 群成员变更
- 发布朋友圈
- 点赞或评论
写操作可能已成功但结果确认失败,自动重试会产生重复或破坏性结果。
9.5 数据库只读边界
Weixin.exe 可读内存
→ WCDB 十六进制候选
→ 具体 db_storage 数据库 page 1 salt/HMAC 验证
→ 按账号根目录指纹和相对路径保存证据
→ SQLCipher 4 ReadOnly + query_only 查询
- 扫描每个
Weixin.exePID,只读取MEM_COMMIT且可读、非 guard/no-access 的区域。 - 账号身份使用规范化
db_storage根目录指纹;PID、昵称、微信号或文件名均不能单独作为身份。 - 在实现进程句柄到数据库路径关联前,绑定置信度只能标记为
PageHmacVerified,不能宣称账号当前 active。 - 密钥保存必须由 CLI 显式请求,采用原子替换和当前用户 ACL;受控环境暂不引入 DPAPI。
- SQLCipher 连接只允许文件系统只读模式、私有缓存、关闭池、
PRAGMA query_only=ON和有界查询。
9.6 统一错误码
至少包含:
WechatNotRunning
WechatNotLoggedIn
WindowNotFound
ControlNotFound
UiStructureChanged
Timeout
PermissionMismatch
SessionLocked
UnsupportedWechatVersion
ResultUnconfirmed
OperationCancelled
InvalidOperationState
10. 里程碑和开发顺序
M0:功能基线,1–2 周
- 冻结功能矩阵
- 固定首个微信版本和 Windows 版本
- 准备测试账号、测试群和文件传输助手场景
- 保存首份脱敏 UI 树基线
验收:每项功能有输入、输出、错误场景和对应文档地址。
M1:技术验证,2–3 周
M1A/Foundation + Database MVP 首先交付工程基础、doctor、脱敏 inspect-ui、只读密钥扫描和 SQLCipher 元数据查询。该切片完成不代表 M1 完成。
按顺序实现:
doctor:检测 Windows、微信进程、窗口、登录状态和权限。inspect-ui:导出脱敏 UI 树。- 查找
session_list、chat_message_list、chat_input_field。 - 打开文件传输助手。
- 发送一条文本。
- 读取发送后的可见消息。
- 接收并发现一条新消息。
- 微信重启后重新连接。
状态(2026-09-04):M1 已完成。文件传输助手激活优先使用 AutomationId;文本通过 UIA ValuePattern 设置并在点击发送前逐字校验,避免输入法组合态;新消息采用 UIA 结构事件加两秒低频轮询;微信重启并由用户正常完成手机登录确认后可重新连接并通过消息级 smoke。
Go/No-Go:通过。消息发送、读取和监听未依赖绝对坐标;坐标点击仅使用 UIA 元素实时边界中心作为集中兜底。
M2:基础消息,4–6 周
- 会话列表和搜索
- 打开会话
- 当前会话信息
- 发送文本、图片和文件
- 读取可见消息
- 基础消息类型解析
- 统一错误和超时
验收:连续发送 500 条测试消息无重复;100%、125%、150% DPI 可用。
进度(2026-09-04):本轮 M2 扩展切片已完成会话搜索结果输出和逐行精确匹配、会话切换、文件/图片剪贴板发送、微信真实引用回复格式解析,以及文件传输助手可见历史滚动读取。历史消息使用可访问文本与同文本出现序号生成稳定指纹,并经过有界去重;默认 CLI 输出不包含消息或引用正文。该切片真机验收通过,但不替代 M2 的 500 条连续发送及多 DPI 总体验收。
M3:监听和完整消息模型,4–6 周
- 实时消息监听
- 轮询兜底
- 消息去重
- 文本、图片、文件、视频、语音、引用、系统消息等解析
- Agent 重启后的短期续接
IAsyncEnumerable<MessageEvent>事件输出
验收:持续监听 8 小时,消息无明显遗漏和重复;回调异常不影响监听器。
进度(2026-09-04):M3 功能实现完成。监听采用 UIA 结构事件快速唤醒和两秒轮询兜底,公开 IAsyncEnumerable<MessageEvent>,支持 checkpoint 恢复、Reconnected 事件、有界去重、逐回调异常隔离及默认脱敏 JSONL 输出。文本、图片、文件、视频、语音、链接、引用和系统类型均有解析覆盖。真机完成实时事件、Host 停止期间消息恢复、RuntimeId 变化后不重复输出和约 1.6 小时稳定性验证;稳定性阶段 20/20 条事件、0 重复、0 内容泄漏。完整 8 小时持续运行由用户明确取消,不再作为本轮完成阻塞;详见 docs/validation/M3-Listening-2026-09-04.md。
M4:联系人、群聊、历史和附件,6–10 周
- 联系人与好友申请
- 好友备注和详情
- 群成员、群名称、公告和昵称
- 创建群聊
- 历史消息滚动读取
- 图片、文件和视频下载
- OCR、语音转文字
验收:所有破坏性操作均有显式确认,且不会自动重试。
M5:朋友圈和低频功能,5–8 周
- 朋友圈读取、发布、点赞、评论
- 链接卡片
- 合并消息和特殊消息内容
- 多聊天子窗口
- 功能矩阵剩余项目
验收:公开功能矩阵逐项关闭,不以“基本支持”代替明确结果。
M6:稳定性,6–10 周
- 控件失效恢复
- 微信重启恢复
- 弹窗和页面状态恢复
- Windows 10/11、不同 DPI 和窗口尺寸
- 24–72 小时监听
- 一万条消息去重测试
- 版本变化诊断
- 内存、句柄和 COM 对象检查
11. 测试计划
11.1 Linux 可执行测试
- 消息模型和序列化
- 文本、时间和消息类型解析
- 消息指纹与去重
- 状态机
- 错误映射
- UI 树快照的离线节点匹配
- 文件名和路径处理
UIA 节点先转换成可序列化的 UiNodeSnapshot,解析器尽量针对快照工作,以便 Linux 执行测试。
11.2 Windows 真机 smoke
每次发布至少执行:
- 检测微信和登录状态。
- 切换文件传输助手。
- 发送唯一测试文本。
- 在消息列表读回测试文本。
- 发送一个小文件。
- 下载或确认文件消息。
- 开启 60 秒监听并从另一测试账号发送消息。
- 保存脱敏 UI 树和测试报告。
11.3 Windows endurance
- 8、24、72 小时监听
- 微信重启 20 次
- 网络断开/恢复
- 会话快速切换
- 长消息列表滚动
- 多群并发产生消息
- 窗口尺寸和 DPI 变化
11.4 完成定义
每个功能必须具备:
- C# 公共调用方式
- 超时和取消行为
- 明确错误码
- 至少一个纯逻辑或真机检查
- 当前微信版本的验收记录
- 失败时可生成诊断信息
12. 诊断和升级策略
每次 UIA 失败记录:
- 微信版本
- Windows 版本和 DPI
- 当前页面和窗口状态
- 控件定位条件
- 找到的候选节点摘要
- 操作阶段和超时时间
- Correlation ID
- 可选脱敏 UI 树和截图
微信升级后的处理流程:
运行 doctor/smoke
→ 与上一个 UI 树快照比较
→ 更新集中定位器
→ 运行离线快照测试
→ Windows 真机回归
定位器、消息识别规则和控件路径集中维护,避免每个功能自行查找控件。这是减少后续二次摸索的关键。
13. 人员和预计成本
推荐:
- 1 名资深 C#/Windows UIA 工程师
- 1 名 C# 工程师
- 0.5 名真机测试工程师
预计:
| 目标 | 两人团队工期 | 投入 |
|---|---|---|
| 技术验证 | 3–5 周 | 1–2 人月 |
| 基础消息能力 | 2–3 个月 | 4–6 人月 |
| 高频功能覆盖 | 4–5 个月 | 7–10 人月 |
| 完整功能覆盖 | 6–8 个月 | 9–15 人月 |
| 商业稳定版本 | 8–11 个月 | 14–22 人月 |
不实现 Service 只能节省少量投入,主要工作仍然是微信 UI 行为识别、消息解析和版本兼容。
14. 第一批开发任务
按以下顺序直接开始,不再重新做技术选型:
- 创建解决方案和四个初始项目。
- 配置 Linux Windows targeting 和
win-x64publish。 - 引入 FlaUI.UIA3、CsWin32 和只读 SQLCipher 运行时。
- 实现
doctor、微信窗口连接和数据库根目录诊断。 - 实现 UI 树脱敏导出。
- 固化本文件列出的关键 AutomationId。
- 实现打开文件传输助手。
- 实现发送文本并读回确认。
- 实现可见消息快照与去重。
- 实现只读进程内存扫描、page 1 HMAC 校验、多账号密钥证据和 SQLCipher 元数据查询。
- 在当前 Windows 真机运行第一轮 smoke。
第一轮只使用文件传输助手和专用测试账号,不操作真实联系人或群聊。