# Real Windows Desktop RPA Example 这是从已跑通业务技能 `D:\OpenClaw\client-marketing\add-friend-wecom` 提炼的 Windows UIA 参考案例。它用于教技术人员和 AI 编程工具如何从真实拾取结果得到稳定定位器,并完成窗口、控件、动作、等待和诊断闭环。 ## 状态 - **技术路线已真实验证**:Windows UIA + Python `uiautomation` - **来源业务已真实跑通**:企业微信添加客户(通讯录 → 新的客户 → 添加 → 搜索 → 发送) - **本目录默认安全模式**:只提供 probe、dry-run、assisted 范式,不默认发送真实邀请 - **不是完整 skill 仓库**:按 Copy map 选择性复制 ## 先读 1. [`../../development/RPA_ELEMENT_LOCATING.md`](../../development/RPA_ELEMENT_LOCATING.md) 2. [`../../development/RPA_DESKTOP.md`](../../development/RPA_DESKTOP.md)(含 Name/Value、最大化激活、同名叶子) 3. 本 README 的“原始拾取到生产定位器” ## 成功案例验证了什么 ```text 枚举目标顶层窗口 → 激活并最大化主窗(勿无条件 SW_RESTORE) → 从 HWND 获取 UIA root / 业务子 pane → 在父容器中定位(Name 与 Value 分开看) → 真实点击并校验后置状态 → 等待子窗口或业务结果 → 处理独立/嵌套弹窗 → probe-ui 诊断 ``` 来源案例还提供 `dry-run / assisted / auto` 三档、频率控制和业务记忆。本 example 只提炼 UIA 元素工程;账号、风控和数据库仍由具体业务技能实现。 本目录 `probe()` 是**最小探针**(主窗 + 通讯录入口,可选尝试新的客户行),**不等于**生产技能完整 probe。 ## 目录结构 ```text real_desktop_rpa/ README.md assets/ element-map.sample.yaml selector-capture.sample.xml scripts/ service/ desktop_session.py uia_locator.py wecom_reference_flow.py util/ selectors.py tests/ test_selector_contract.py ``` ## 原始拾取到生产定位器 ### 搜索框(添加客户窗) ```text 原始:Window(SearchExternalsWnd) → 多层 Layout/index → search_layout → searchedit 提炼:窗口 → search_layout → Name=searchedit ``` ### 新的客户(易错) ```text 原始:通讯录 pane → wlist_view → item[2] → status_layout → main_chattext 提炼:wlist_view 内找 子控件 main_chattext.Value=新的客户 的那一行,再点该行 status_layout 禁止:全树第一个 Name=status_layout(常为「群聊」) 禁止:把选择器标题「新的客户」当成 UIA Name 去搜 ``` ### 添加按钮 ```text 提炼:search_external → wbtn_container(子文案 Value=添加) 禁止:搜索旁 plus_button 下的同名 wbtn_container ``` 正确提炼方式: 1. 保留稳定顶层窗口:进程、Window Class、标题;需要时加上业务子 pane。 2. 保留最小业务父容器。 3. 叶子用稳定 Name **和/或** Value / 子控件 Value。 4. 删除只反映当前布局的深层 index;index 仅作已验证兜底并写清含义。 5. 验证父容器内候选数量为 `1`。 6. 重启应用后再次验证。 不要把完整 XML 路径或未校验的 `item[0]` 原样变成生产定位器。 ## Element map 本目录的 [`assets/element-map.sample.yaml`](assets/element-map.sample.yaml) 只展示来源案例的元素登记方法。复制后必须重新拾取目标软件并全部替换。 关键规则: - 窗口不唯一时失败,不取 `hwnds[0]`。 - 控件不唯一时失败,不取第一个匹配。 - `item`、`status_layout`、`wbtn_container` 等通用 Name 必须放进稳定父容器,并用文案校验。 - 行顺序不是身份;用业务文案(Value)选择结果行。 - 主窗依赖完整侧栏时先 maximize;`activate(maximize=False)` 不得冲掉已最大化状态。 - 只有主定位成功、窗口前台且矩形有效时,才允许从 UIA BoundingRectangle 降级坐标点击。 ## 三种实施模式 | 模式 | 行为 | 用途 | |---|---|---| | `probe` | 只检查依赖、窗口和关键控件 | 安装、自检、版本变更排障 | | `dry-run` | 导航并填写,提交前停止 | 开发和验收默认 | | `assisted` | 填写后等待用户人工确认 | 不可逆动作或现场联调 | 业务技能若增加 `auto`,必须实现明确确认策略、频率限制、业务后置状态和 `RESULT_UNCONFIRMED`。 ## Copy map | 来源 | 目标 | 说明 | |---|---|---| | `scripts/service/desktop_session.py` | `scripts/service/desktop_session.py` | 顶层窗口枚举、唯一性、激活/最大化 | | `scripts/service/uia_locator.py` | `scripts/service/uia_locator.py` | 作用域内唯一定位(含 Value)、点击、输入 | | `scripts/util/selectors.py` | `scripts/util/_selectors.py` | element spec;必须全部替换 | | `scripts/service/wecom_reference_flow.py` | `scripts/service/_flow.py` | 只复制流程分层,不复制企微 selector | | `assets/element-map.sample.yaml` | `assets/-element-map.yaml` | 真实拾取后填写 | | `tests/test_selector_contract.py` | `tests/test_selector_contract.py` | 定位器契约测试思路 | ## 必须补齐的业务能力 - 目标应用安装/版本 doctor - 真实业务元素清单 - 失败截图、UIA树和顶层窗口快照 - Activity/RpaVideoSession 步骤 - 不可逆动作确认 - 业务成功/失败/结果不明确状态 - 频率限制、幂等和断点续跑 - 真实集成测试(默认不进 CI) ## 禁止照抄 - `WXWork`、`WeWorkWindow`、`SearchExternalsWnd` - `org_op_new`、`searchedit`、`wbtn_container`、`main_chattext` - 企业微信列表第 0/1/2 行含义或固定 index - 来源案例的本机路径、账号和业务数据 - 任何未经目标软件真实拾取验证的 fallback ## 验收 - `probe` 能明确报告依赖、窗口和关键元素(生产技能覆盖关键跳转节点) - 每个关键元素在目标作用域内唯一 - 关闭重开软件后仍能定位 - 多窗口时不会误选 - UI变化时停止并保存截图/UIA树 - dry-run 不执行不可逆提交 - assisted 清楚提示用户确认 - 提交后仅在业务后置状态成立时报告成功