fix(desktop-wake): only OBJID_CLIENT DuiLib path to stop UIA core crash (1.2.5)
All checks were successful
Publish Python Package to Gitea / publish (push) Successful in 25s
All checks were successful
Publish Python Package to Gitea / publish (push) Successful in 25s
Skip UiaRoot MSAA spoofing, sync GETOBJECT, and SPI screen-reader for n2-wake. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "jiangchang-platform-kit"
|
||||
version = "1.2.4"
|
||||
version = "1.2.5"
|
||||
description = "匠厂平台共享组件:Skill 实体 SDK + 桌面应用自动化 SDK + 桌面 UIA 暖树"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.10"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# jiangchang_desktop_wake 验收(ensure 主路径,1.2.4+)
|
||||
# jiangchang_desktop_wake 验收(ensure 主路径,1.2.5+)
|
||||
|
||||
正式对外路径是 **`ensure`**(内部:`activate` → `desktop-wake --mode n2-wake` → `probe`)。
|
||||
`n2-wake` **不再**在企微进程内跑 UIAutomation FindAll(防 `uiautomationcore.dll` 崩溃);判暖只看进程外 probe。
|
||||
`n2-wake`:**仅 OBJID_CLIENT** 走 DuiLib;不做进程内 FindAll、不同步 GETOBJECT、不 SPI 读屏;判暖只看进程外 probe。
|
||||
`c2` / `inject` 仅诊断用。
|
||||
|
||||
## 0. 编译(企微先完全退出,含托盘)
|
||||
@@ -57,7 +57,7 @@ python -m jiangchang_desktop_wake probe --profile wecom
|
||||
| `probe_after.findall_count` | **≥ 80**(常见 300+) |
|
||||
| markers | 含 `con_op`、`searchedit` |
|
||||
| 企微 UI | 可点,无「未响应」 |
|
||||
| provider | `done=1` `subclass=1` `dui=1` `no_inproc_uia=1`;`lr_client≠0` 更佳 |
|
||||
| provider | `done=1` `subclass=1` `dui=1` `client_only=1` `no_inproc_uia=1` |
|
||||
| subclass | `method=SetWindowLongPtr`,`ok=1`,`userdata≠0` |
|
||||
| 企微进程 | **不崩**、无「错误报告」对话框 |
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
桌面 UIA Provider **暖树**(与 `jiangchang_skill_core` / `jiangchang_desktop_sdk` 平级)。
|
||||
|
||||
企微主路径:注入 `wecom_wake.dll`,对主窗 `SetWindowLongPtr` 后走 DuiLib
|
||||
`GetAccessible` / `OnGetObject`;**不在进程内 FindAll**(1.2.4+,避免 uiautomationcore 崩溃)。
|
||||
企微主路径:注入 `wecom_wake.dll`,对主窗 `SetWindowLongPtr` 后仅对
|
||||
`OBJID_CLIENT` 走 DuiLib `GetAccessible`(1.2.5+;避免 UiaRoot/MSAA 混用崩 uiautomationcore)。
|
||||
|
||||
可整目录删除:`src/jiangchang_desktop_wake` + `tests/desktop_wake`。
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -152,8 +152,6 @@ namespace JiangchangDesktopWake
|
||||
try
|
||||
{
|
||||
Activate(hwnd);
|
||||
EnableScreenReaderFlag(); // 进程外 SPI:部分 App 见“读屏器”会挂树
|
||||
|
||||
// n1/auto:进程外 UIA
|
||||
// n2:仅注入探针
|
||||
// n2-wake:注入 + 远程 WakeProvider(C2,无钩子)
|
||||
@@ -163,6 +161,9 @@ namespace JiangchangDesktopWake
|
||||
bool doWakeProvider = (mode == "n2-wake") && profile == "wecom";
|
||||
// n2-wake:不在 exe 内做 UIA 深扫(易跟着目标进程一起挂);暖树由 Python probe 判定
|
||||
bool doN1 = (mode == "n1" || mode == "auto" || mode == "n2-hook");
|
||||
// n2-wake 不再 SPI_SETSCREENREADER:会触发 UiaRoot 查询,测试机曾崩 uiautomationcore
|
||||
if (!doWakeProvider)
|
||||
EnableScreenReaderFlag();
|
||||
|
||||
if (doN2)
|
||||
{
|
||||
|
||||
@@ -6,10 +6,11 @@
|
||||
* WakeTarget — 旧子类化(危险,仅 n2-hook)
|
||||
* JcCallWndProc — 旧钩子(危险,仅 n2-hook)
|
||||
*
|
||||
* 1.2.4 主路径(防 uiautomationcore 崩):
|
||||
* - SetWindowLongPtr 子类化,WM_GETOBJECT → DuiLib GetAccessible/OnGetObject
|
||||
* - 重入守卫:处理 GETOBJECT 时不再二次进 DuiLib
|
||||
* - 不做进程内 UIAutomation FindAll / AccessibleObjectFromWindow(判暖交给进程外 probe)
|
||||
* 1.2.5 主路径(防 uiautomationcore 崩):
|
||||
* - SetWindowLongPtr 子类化;仅 OBJID_CLIENT 走 DuiLib GetAccessible
|
||||
* - UiaRootObjectId 等原样交给旧 WndProc(禁止用 MSAA Lresult 冒充 UIA root)
|
||||
* - 不做进程内 UIAutomation FindAll;不做同步 SendMessage(GETOBJECT)
|
||||
* - 重入守卫;判暖交给进程外 probe
|
||||
*/
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
@@ -122,11 +123,9 @@ static HWND ReadTargetHwnd()
|
||||
|
||||
static void NudgeWinEvents(HWND hwnd)
|
||||
{
|
||||
/* 只异步点 CLIENT,绝不 Post UiaRootObjectId(易进 uiautomationcore 崩) */
|
||||
NotifyWinEvent(EVENT_OBJECT_FOCUS, hwnd, OBJID_CLIENT, CHILDID_SELF);
|
||||
NotifyWinEvent(EVENT_SYSTEM_ALERT, hwnd, OBJID_CLIENT, CHILDID_SELF);
|
||||
PostMessageW(hwnd, WM_GETOBJECT, 0, (LPARAM)OBJID_CLIENT);
|
||||
PostMessageW(hwnd, WM_GETOBJECT, 0, (LPARAM)OBJID_WINDOW);
|
||||
PostMessageW(hwnd, WM_GETOBJECT, 0, (LPARAM)UiaRootObjectId);
|
||||
PostMessageW(hwnd, WM_NULL, 0, 0);
|
||||
}
|
||||
|
||||
@@ -144,8 +143,16 @@ static bool ResolveDuiLib()
|
||||
return g_fnGetAccessible != NULL || g_fnOnGetObject != NULL;
|
||||
}
|
||||
|
||||
static bool IsClientObjectId(LPARAM lParam)
|
||||
{
|
||||
return (LONG)lParam == (LONG)OBJID_CLIENT;
|
||||
}
|
||||
|
||||
static LRESULT TryDuiLibGetObject(HWND hwnd, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
/* 只服务 MSAA CLIENT。UiaRootObjectId 用 LresultFromObject(IAccessible) 会搞崩 UIA core */
|
||||
if (!IsClientObjectId(lParam))
|
||||
return 0;
|
||||
if (!ResolveDuiLib())
|
||||
return 0;
|
||||
|
||||
@@ -194,7 +201,8 @@ static LRESULT HandleGetObject(
|
||||
else if (oldProc)
|
||||
r = CallWindowProcW(oldProc, hwnd, WM_GETOBJECT, wParam, lParam);
|
||||
|
||||
if (r == 0)
|
||||
/* 非 CLIENT(含 UiaRootObjectId):绝不伪造返回值 */
|
||||
if (r == 0 && IsClientObjectId(lParam))
|
||||
r = TryDuiLibGetObject(hwnd, wParam, lParam);
|
||||
|
||||
t_inGetObject = 0;
|
||||
@@ -263,11 +271,10 @@ static bool InstallDuiSubclass(HWND hwnd)
|
||||
return true;
|
||||
}
|
||||
|
||||
/* 只装子类化 + 异步 nudge;可选一次短超时 GETOBJECT 看 lr(无进程内 UIA) */
|
||||
/* 只装子类化 + 异步 nudge;禁止同步 SendMessage(GETOBJECT) */
|
||||
static void DoSafeWake(HWND hwnd)
|
||||
{
|
||||
char line[512];
|
||||
LRESULT lrClient = 0;
|
||||
int subclass_ok = 0;
|
||||
int dui_ok = 0;
|
||||
|
||||
@@ -276,21 +283,13 @@ static void DoSafeWake(HWND hwnd)
|
||||
subclass_ok = InstallDuiSubclass(hwnd) ? 1 : 0;
|
||||
|
||||
NudgeWinEvents(hwnd);
|
||||
|
||||
DWORD_PTR smResult = 0;
|
||||
if (SendMessageTimeoutW(
|
||||
hwnd, WM_GETOBJECT, 0, (LPARAM)OBJID_CLIENT,
|
||||
SMTO_ABORTIFHUNG, 2000, &smResult)) {
|
||||
lrClient = (LRESULT)smResult;
|
||||
}
|
||||
|
||||
NudgeWinEvents(hwnd);
|
||||
|
||||
sprintf_s(line,
|
||||
"hwnd=%p sta_tid=%lu lr_client=%ld subclass=%d dui=%d "
|
||||
"hwnd=%p sta_tid=%lu subclass=%d dui=%d "
|
||||
"dui_hits=%ld getobject_hits=%ld reenter_skip=%ld "
|
||||
"no_inproc_uia=1 done=1\r\n",
|
||||
hwnd, GetCurrentThreadId(), (long)lrClient, subclass_ok, dui_ok,
|
||||
"client_only=1 no_sync_getobject=1 no_inproc_uia=1 done=1\r\n",
|
||||
hwnd, GetCurrentThreadId(), subclass_ok, dui_ok,
|
||||
(long)g_duiHits, (long)g_getobjectHits, (long)g_reenterSkip);
|
||||
WriteMarker("jiangchang_desktop_wake_provider.txt", line);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user