6.7 KiB
6.7 KiB
A-route 离线打开真实 frmP2PChat 会话窗口
日期:2026-07-11
分支:codex/a-route-open-real-chat-window
目标:不登录、不连服务端,在本机离线样本中打开真实 IMPP.Client.Business.ChatManager.SingleChat.frmP2PChat 窗口,供后续 RPA 对真实窗口做 UIA 控制。
结论
已经在未登录/离线环境下打开真实 frmP2PChat。
成功命令:
powershell -NoProfile -ExecutionPolicy Bypass -File scripts\open-offline-real-frmP2PChat.ps1 -RuntimeMode Deps -ShowWindow -HoldSeconds 1
成功产物:
- 结果 JSON:
E:\coding\codex\isphere-ai-bridge\runs\offline-chat-window\real-frmP2PChat-result-20260711-205312.json - HWND:
0xC0CB4 - 截图:
E:\coding\codex\isphere-ai-bridge\runs\offline-chat-window\real-frmP2PChat-20260711-205312.png - UIA dump:
E:\coding\codex\isphere-ai-bridge\runs\offline-chat-window\uia-dump-real-frmP2PChat-20260711-205312.json - UIA root:
automation_id = frmP2PChatcontrol_type = Windowframework_id = WinFormvisible = true
UIA dump 已确认可见关键控件:
rtbRecvMessagertbSendMessagebtnSend
窗口内显示“您已处于离线状态,无法发送消息,请上线后再次尝试!”。这是预期状态;本轮目标不是发送消息,也不是上传文件,只是打开真实会话窗口。
新增脚本
1. 真实窗口打开脚本
scripts/open-offline-real-frmP2PChat.ps1
关键能力:
- 自动切到 32-bit PowerShell,避免 x86 客户端程序集
BadImageFormatException。 - 只读加载真实客户端目录:
runs/offline-real-client-window/full/zyl/Impp - 使用
AssemblyResolve从真实客户端目录解析依赖。 - 构造真实类型:
IMPP.Client.Business.ChatManager.SingleChat.frmP2PChat - 支持不 Show 的构造验证,也支持
-ShowWindow真实显示、截图和 UIA dump。 - 捕获 WinForms
ThreadException,输出 IL offset、堆栈和 JSON 证据,避免 .NET 异常弹窗卡死。
2. 构造函数 IL / NullRisk 提取脚本
scripts/extract-frmP2PChat-il-risk.ps1
输出:
- 完整构造函数 IL:
runs/offline-chat-window/frmP2PChat-ctor.il.txt callvirt/ldfldNullRisk CSV:runs/offline-chat-window/frmP2PChat-ctor-null-risk.csv- 风险摘要:
runs/offline-chat-window/frmP2PChat-ctor-null-risk.md
提取结果:
- 构造函数源 IL 行:
406271-406860 - 构造函数行数:
590 callvirt/ldfld风险项:150
关键 IL 证据
构造函数签名:
frmP2PChat(com.vision.smack.Chat chat, string pluginInfo, string extendTabJson)
高信号 NullRisk:
| IL | 证据 | 需要补的运行态 |
|---|---|---|
IL_00f6 |
XMPPConnection::add_OnConnectError |
IMPPManager.Instance.Connection / backing field |
IL_0111 |
XMPPConnection::add_OnReConnectOk |
同上 |
IL_013b / IL_0140 |
P2PChat::get_OtherJid() / Jid::getBareJid() |
P2PChat.OtherJid |
IL_0156 |
IMPPManager::get_UserInfo() |
IMPPManager._userInfo |
IL_0575 |
MessageCenter::add_OnTcpMessageArrived |
IMPPManager.MessageCenter |
IL_0614 |
RosterManager::UpdateStrangerStatus |
IMPPManager.RosterManager |
IL_0631 |
BaseConfig::VisualPhoneEnable() |
Config.BaseConfig |
Show 阶段新增证据:
| IL | 证据 | 处理 |
|---|---|---|
frmP2PChat_Load IL_004d/0058 |
Config::get_BaseConfig() 后 BaseConfig::RemoteControlVisible() |
补 Config.<BaseConfig>k__BackingField |
frmChatBase_Activated IL_0000/0005 |
IMPPManager.get_Instance().get_frmMain().BringModalFormToFront() |
补 IMPPManager.<frmMain>k__BackingField |
frmP2PChat_Load IL_137f |
UserInfoManager.getUserInfo(otherBareJid,true) 后使用 UserInfo::get_CompanyID() |
构造完成后预热 UserInfoCache |
注意:UserInfoCache 不能在 frmP2PChat 构造前预热。过早预热会让构造函数进入 UCUserInformation.LoadUserInfo(UserInfo),在 UCUserInformation::LoadUserInfo IL_0085 触发新的 NRE。当前脚本是在真实窗体构造完成后、Show() 前预热缓存。
最小 fake runtime 清单
当前成功路径最小补齐如下:
IMPPManager.Instance<MessageCenter>k__BackingField<frmMain>k__BackingFieldLogonUser_userInfo_rosterUserInfoList
SmarkManager<SmarkManagerInstance>k__BackingField
XMPPConnectionJidUserNameLoginStateCompanyIDResource_packetListeners_packetCollectors
IMPPManagerinherited manager fields/propertiesConnectionand<Connection>k__BackingFieldIsConnectedand<IsConnected>k__BackingFieldPresenceManagerand backing fieldP2PChatManagerand backing fieldRosterManagerand backing field
- Config
ConfigSystemManager.configConfig.<BaseConfig>k__BackingFieldConfig.<UserInfo>k__BackingFieldConfig.<LoginInfo>k__BackingField
UserInfoCache- 在
frmP2PChat构造后、Show()前加入自己和对端的 JID/ID 映射。
- 在
- Chat 对象
- 真实
com.vision.smack.P2PChat OtherJid = codex-probe@offline.local
- 真实
验证命令
powershell -NoProfile -ExecutionPolicy Bypass -File scripts\test-extract-frmP2PChat-il-risk.ps1
powershell -NoProfile -ExecutionPolicy Bypass -File scripts\extract-frmP2PChat-il-risk.ps1 -OutDir runs/offline-chat-window
powershell -NoProfile -ExecutionPolicy Bypass -File scripts\test-open-offline-real-frmP2PChat-contract.ps1
powershell -NoProfile -ExecutionPolicy Bypass -File scripts\open-offline-real-frmP2PChat.ps1 -RuntimeMode Deps
powershell -NoProfile -ExecutionPolicy Bypass -File scripts\open-offline-real-frmP2PChat.ps1 -RuntimeMode Deps -ShowWindow -HoldSeconds 1
当前边界
- 已成功打开真实
frmP2PChat。 - UIA 可 dump 到真实
frmP2PChat、rtbRecvMessage、rtbSendMessage、btnSend。 - 离线环境下窗口会提示无法发送消息,这是客户端真实离线状态表现,不影响后续 RPA 窗口定位。
- 本轮没有处理真实发送、真实上传、真实登录态。
btnSendFile在这次真实离线 UIA dump 中没有以btnSendFileautomation id 暴露;后续如果 RPA 需要上传文件,需要另开节点定位真实工具栏按钮或菜单路径。
下一轮建议
- 把 A-route RPA 的窗口定位目标从 synthetic probe 切到真实
frmP2PChat:- root
automation_id=frmP2PChat - send box
automation_id=rtbSendMessage - send button
automation_id=btnSend
- root
- 如果弹出“企业信息获取失败”影响自动化,单独加一个非阻塞关闭弹窗步骤。
- 如果后续需要文件按钮,再专门分析真实工具栏图标按钮、菜单项和
ToolStrip命中路径。