From e1f162aa8276dd0367a36d9be897cc1466c53079 Mon Sep 17 00:00:00 2001 From: yu <191972707@qq.com> Date: Tue, 3 Nov 2026 17:19:22 +0800 Subject: [PATCH] =?UTF-8?q?=E9=94=99=E8=AF=AF=E4=BF=A1=E6=81=AF=E8=A7=A3?= =?UTF-8?q?=E7=A0=81=E4=B8=8E=E7=AA=97=E5=8F=A3=E5=88=97=E8=A1=A8=E6=8F=90?= =?UTF-8?q?=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/capabilities/desktop.ts | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/main/capabilities/desktop.ts b/src/main/capabilities/desktop.ts index 1f51317..b6d9d55 100644 --- a/src/main/capabilities/desktop.ts +++ b/src/main/capabilities/desktop.ts @@ -78,6 +78,16 @@ function encoded(command: string): string { return Buffer.from(command, "utf16le").toString("base64"); } +/** 从 PowerShell 错误输出里提取 CLIXML 段的真实错误文本(否则显示为乱码转义序列) */ +function decodeCliXml(detail: string): string { + const lines = [...detail.matchAll(/(.*?)<\/S>/gs)].map((m) => m[1]); + if (lines.length === 0) return detail; + // 只留「+ 类别/错误消息」首行, 去掉位置堆栈噪声; _xHHHH_ 是 CLIXML 转义 + const decoded = lines.join("\n").replace(/_x([0-9A-Fa-f]{4})_/g, (_, h) => String.fromCharCode(parseInt(h, 16))); + const first = decoded.split("\n").map((l) => l.trim()).filter((l) => l && !l.startsWith("所在位置") && !l.startsWith("+") && !l.startsWith("~~") && !l.includes("CategoryInfo") && !l.includes("FullyQualifiedErrorId") && !l.startsWith(" { try { // Windows PowerShell 的默认输出编码依机器代码页变化;Node 按 UTF-8 解码管道。 @@ -89,7 +99,8 @@ export async function powershell(command: string, timeout = 30000): Promise { /** 把匹配标题的窗口带到前台;多招式依次兜底(应用点击「运行」后自身是前台, * Windows 前台锁定策略会拒绝普通 SetForegroundWindow,最小化再恢复可绕过) */ function activateWindowScript(selector: string): string { + const safeTitle = selector.replace(/'/g, "''"); return `$p = Get-Process | Where-Object { $_.MainWindowTitle -and $_.MainWindowTitle -like ${psString(`*${selector}*`)} } | Select-Object -First 1 -if (-not $p) { throw '找不到窗口:${selector.replace(/'/g, "''")}' } +if (-not $p) { $vis = (Get-Process | Where-Object { $_.MainWindowTitle } | Select-Object -First 12 | ForEach-Object { '『' + $_.MainWindowTitle + '』' }) -join ' '; throw ('找不到窗口:${safeTitle}。当前可见窗口标题: ' + $vis) } Add-Type -MemberDefinition '[DllImport("user32.dll")] public static extern IntPtr GetForegroundWindow(); [DllImport("user32.dll")] public static extern bool ShowWindow(IntPtr h, int cmd); [DllImport("user32.dll")] public static extern bool IsIconic(IntPtr h); [DllImport("user32.dll")] public static extern bool SetForegroundWindow(IntPtr h); [DllImport("user32.dll")] public static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, UIntPtr dwExtraInfo); [DllImport("user32.dll")] public static extern uint GetWindowThreadProcessId(IntPtr hWnd, IntPtr pid); [DllImport("user32.dll")] public static extern bool AttachThreadInput(uint a, uint b, bool attach); [DllImport("user32.dll")] public static extern void SwitchToThisWindow(IntPtr hWnd, bool fAltTab); [DllImport("kernel32.dll")] public static extern uint GetCurrentThreadId();' -Name RpaFocus2 -Namespace WinRpaFocus2 | Out-Null $h = $p.MainWindowHandle if ([WinRpaFocus2.RpaFocus2]::IsIconic($h)) { [void][WinRpaFocus2.RpaFocus2]::ShowWindow($h, 9); Start-Sleep -Milliseconds 150 }