fix: reject UI operations when the input desktop is unavailable

This commit is contained in:
2026-09-06 02:14:16 +08:00
parent c35a4a1051
commit 1494094651
9 changed files with 203 additions and 2 deletions
@@ -0,0 +1,31 @@
# 锁定桌面的失败保护(2026-09-05)
## 问题与修复
Windows Session 1 断开并出现同会话的 `LogonUI` 后,UIA 仍可读取微信窗口。单靠 `Environment.UserInteractive`、窗口存在和控件齐全,会把不可操作的桌面误判为可发送,甚至先写入测试草稿再在鼠标点击时失败。
共享检查使用当前进程的非零会话、`Environment.UserInteractive` 和公开 Win32 `GetCursorPos` 的输入桌面访问结果。不尝试解锁、切换到登录桌面或重启微信。
- `doctor` 新增 `InputDesktopAvailable`;不可访问时报告 `SessionLocked`。
- 会话附着、输入步骤、鼠标点击和独立监听绑定前检查桌面。
- 监听启动时立即拒绝不可操作的桌面;运行期间重新绑定也检查,不能把锁屏 UIA 快照算作正常心跳。
## 已验证的范围
本次从 Git 暂存区单独导出锁屏保护源码,构建并发布 `releases/desktop-guard-only-1`;不包含工作区尚待验收的命名文本发送改动。
- Windows 10.0.19044,微信 4.1.13.63,已锁定/断开的 Session 1。
- 发布程序 SHA-256:`355AA5DA758998A07D0BA7FA883858E0B664F5FDB8745BFFE322F383F94BEF2A`。
- Core 72/72 通过;完整 Release 构建与 self-contained 发布为 0 警告、0 错误。
- `doctor` 退出 2,`InputDesktopAvailable=false`,错误含 `SessionLocked`。
- 只读 `inspect-ui` 退出 0:证明 UIA 可读并不等于桌面可操作。
- `smoke`、`chat send`、`chat monitor` 均退出 1,并明确报告 `SessionLocked`;这是本负向测试的预期结果,不是正向 smoke 通过。
- 测试独立读取输入框值并仅在内存中计算摘要,确认执行前后草稿未变;没有创建监听 checkpoint。
复现:`scripts/windows/Test-LockedDesktop.ps1 -Executable <exe> -OutputDirectory <新目录>`。脚本要求桌面已经不可操作;它不会主动锁屏或断开会话。
脱敏结果:`evidence/Locked-Desktop-20260905/`。
## 仍未验收
原会话需要由用户重新连接并解锁,之后补做正向发送/重复文本/双窗口事件隔离回归。此前点击失败与桌面不可访问有关,不能据此声称旧控件引用是已经证实的唯一根因。本记录不代表完整 M6 验收,更不能替代 8/24/72 小时耐久测试。
@@ -0,0 +1,71 @@
{
"OperatingSystem": "Microsoft Windows NT 10.0.19044.0",
"UserInteractive": true,
"CurrentSessionId": 1,
"Processes": [
{
"Id": 8912,
"WorkingSetBytes": 54181888,
"SessionId": 1,
"Version": "4.1.13.63",
"CanReadMemory": true,
"AccessError": null,
"HandleCount": 2527,
"ThreadCount": 124
},
{
"Id": 11064,
"WorkingSetBytes": 9629696,
"SessionId": 1,
"Version": "4.1.13.63",
"CanReadMemory": true,
"AccessError": null,
"HandleCount": 301,
"ThreadCount": 10
},
{
"Id": 17780,
"WorkingSetBytes": 8536064,
"SessionId": 1,
"Version": "4.1.13.63",
"CanReadMemory": true,
"AccessError": null,
"HandleCount": 376,
"ThreadCount": 15
},
{
"Id": 2436,
"WorkingSetBytes": 1191936,
"SessionId": 1,
"Version": "4.1.13.63",
"CanReadMemory": true,
"AccessError": null,
"HandleCount": 219,
"ThreadCount": 19
},
{
"Id": 14720,
"WorkingSetBytes": 987136,
"SessionId": 1,
"Version": "4.1.13.63",
"CanReadMemory": true,
"AccessError": null,
"HandleCount": 216,
"ThreadCount": 13
}
],
"WindowFound": true,
"RequiredControls": {
"MainView": true,
"session_list": true,
"chat_message_page": true,
"chat_message_list": true,
"chat_input_field": true,
"tool_bar_accessible": true
},
"DataRootCount": 1,
"Errors": [
"SessionLocked"
],
"InputDesktopAvailable": false
}
@@ -0,0 +1,15 @@
{
"InspectExit": 0,
"DraftUnchanged": true,
"ListenerError": "SessionLocked",
"SendExit": 1,
"SendError": "SessionLocked",
"SmokeExit": 1,
"DoctorExit": 2,
"InputDesktopAvailable": false,
"ListenerExit": 1,
"BinarySha256": "355AA5DA758998A07D0BA7FA883858E0B664F5FDB8745BFFE322F383F94BEF2A",
"Success": true,
"SmokeError": "SessionLocked",
"CheckpointCreated": false
}