From baa4e860582f09f7fd356d62e63a8409cd6b2c7b Mon Sep 17 00:00:00 2001 From: jiangchen <1703935164@qq.com> Date: Sun, 27 Sep 2026 14:14:23 +0800 Subject: [PATCH] =?UTF-8?q?fix(shell):=20=E4=BF=AE=E5=A4=8D=E9=A1=B5?= =?UTF-8?q?=E9=9D=A2=E6=8C=89=E9=92=AE=E5=85=A8=E5=A4=B1=E6=95=88=EF=BC=88?= =?UTF-8?q?param=20=E5=90=8D=E4=B8=8D=E8=83=BD=E5=8F=AB=20args=EF=BC=89+?= =?UTF-8?q?=20-NoExclude=20=E4=B8=8D=E5=86=8D=E6=88=90=E4=B8=BA=E9=BB=98?= =?UTF-8?q?=E8=AE=A4=EF=BC=9BREADME=20=E8=A1=A5=E9=AA=8C=E8=AF=81=E6=96=B9?= =?UTF-8?q?=E6=B3=95=E4=B8=8E=E8=B8=A9=E5=9D=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 31 +++++++++++++++++++++++++++++++ shell/float-window.ps1 | 16 ++++++++++------ 2 files changed, 41 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 9871e54..ef3e6b5 100644 --- a/README.md +++ b/README.md @@ -106,6 +106,37 @@ shell\run-float.cmd -Action pin # 给正在运行的实例 5. **`CoreWebView2Environment.CreateAsync` 的参数顺序是 `(browserExecutableFolder, userDataFolder, options)`**,传错会得到 "Couldn't find a compatible Webview2 Runtime"。 6. **高 DPI**:WinForms 会把逻辑尺寸按缩放放大,位置要按真实 `Width/Height` 夹回屏幕内。 7. `.ps1` 里出现中文时**必须存成 UTF-8 with BOM**,否则 PowerShell 5.1 按 GBK 读会把脚本解析坏(`tools/fix-bom.ps1` 专门干这个)。 +8. **cordis:`ctx.set` 之前必须 `ctx.provide`**。漏了会抛 `cannot set property "floatWindow" without provide`,后果不是"少个功能"而是**整个插件树加载失败、DSH 进程直接退出**。本轮就是在隔离实例里实测复现后修掉的。 +9. **PowerShell 事件处理器里参数不能叫 `$args`**:它是自动变量,会把整个事件参数数组占住,于是 `$e.TryGetWebMessageAsString()` 变成"数组没有这个方法"——表现为**页面所有按钮(含右下角缩放、置顶、锁定、全屏、设置)全部失效**。正确写法是 `param($s, $e)`。 +10. **profile 的 `package.json` 不能带 BOM**:Node 读 JSON 会报 `SyntaxError: Unexpected token '锘?`。用 `[IO.File]::WriteAllText(..., UTF8Encoding($false))` 写。 + +## 怎么验证(可复现) + +不需要动你正在用的 DSH: + +```powershell +# 1) 造一个隔离的 DSH_HOME,profile 只装 base + web-app + 本插件 +$t = '.runtime\testhome' +New-Item -ItemType Directory -Force -Path "$t\profiles\web\node_modules" | Out-Null +# package.json(bundles 只留三个) + cordis.yml/cordis.patch.yml 见 README 上文 +cmd /c mklink /J "$t\profiles\web\node_modules\dsh-float-window" "$PWD" + +# 2) 起第二个实例(8099),观察插件是否被加载 +$env:DSH_HOME = (Resolve-Path $t) +node web --port 8099 +# -> 出现 endpoint.json 且无 "plugin tree failed to load" 即通过 + +# 3) 直接打插件路由 +curl http://127.0.0.1:8099/dsh-float-window/health +curl http://127.0.0.1:8099/dsh-float-window/state +curl -N http://127.0.0.1:8099/dsh-float-window/events # SSE,每秒一帧 + +# 4) 让浮窗连到这个测试实例(看视觉效果时再加 -NoExclude) +shell\run-float.cmd -DshHome $t -NoExclude +# 标题栏应变成绿点 + 127.0.0.1:8099 +``` + +`tools/smoke-host.mjs` 则是更轻的一层:假 ctx 直接调 `apply()`,验证路由/SSE/工具注册不抛异常。 ## 配置 diff --git a/shell/float-window.ps1 b/shell/float-window.ps1 index 822cf55..4edbb96 100644 --- a/shell/float-window.ps1 +++ b/shell/float-window.ps1 @@ -198,7 +198,7 @@ $script:state = [ordered]@{ posLock = $false sizeLock = $false opacity = $Opacity - exclude = (-not $NoExclude) + exclude = $true # 默认抓屏隐身;-NoExclude 只在运行时覆盖,绝不落盘成默认值 scale = 1.0 fullscreen = $false backdrop = if ($Backdrop) { $Backdrop } else { 'opaque' } @@ -339,19 +339,23 @@ function Send-Endpoint { try { $ep = Get-Content $endpointFile -Raw | ConvertFrom-Json $payload.baseUrl = $ep.baseUrl; $payload.token = $ep.token - } catch {} + } catch { Log "endpoint parse failed: $($_.Exception.Message)" } } + Log "push endpoint -> $($payload.baseUrl)" Send-ToPage $payload } # ---------------------------------------------------------------- 页面消息处理 $onWebMessage = { - param($sender, $args) + # 参数不能叫 $args —— 那是 PowerShell 的自动变量,会被整个事件参数数组占住, + # 于是 TryGetWebMessageAsString 找不到(实测:页面全部按钮失效、ready 握手丢失)。 + param($s, $e) try { - $msg = $args.TryGetWebMessageAsString() - if (-not $msg) { $msg = $args.WebMessageAsJson } + $msg = $e.TryGetWebMessageAsString() + if (-not $msg) { $msg = $e.WebMessageAsJson } $m = $msg | ConvertFrom-Json - } catch { return } + } catch { Log "webmessage parse failed: $($_.Exception.Message)"; return } + if ($m.cmd -and $m.cmd -ne 'drag' -and $m.cmd -ne 'resize') { Log "page cmd: $($m.cmd)" } switch ($m.cmd) { 'ready' { Push-State; Send-Endpoint } 'drag' { if (-not $script:state.posLock) { [void][DshFloat.Native]::ReleaseCapture(); [void][DshFloat.Native]::SendMessage($form.Handle, 0xA1, [IntPtr]2, [IntPtr]::Zero) } }