Skip to content

fix(windows): hide child console windows via a hidden Harness console - #289

Merged
yaojin3616 merged 1 commit into
dataelement:mainfrom
ump45nose:fix/windows-pwsh-console-flash
Sep 4, 2026
Merged

yaojin3616 merged 1 commit into
dataelement:mainfrom
ump45nose:fix/windows-pwsh-console-flash

Conversation

@ump45nose

Copy link
Copy Markdown
Contributor

Summary

On Windows, every pwsh (and other console tool) call briefly flashes a console window. The root cause: the desktop spawns the Harness with detached: true + windowsHide: true (DETACHED_PROCESS | CREATE_NO_WINDOW), so the Harness has no console. A console child spawned from a console-less parent with only windowsHide (CREATE_NO_WINDOW) still allocates a fresh, briefly-visible console — the flash (issue #233).

Fix

Give the Harness its own console and hide it at startup (AllocConsole + ShowWindow(..., SW_HIDE)). Its children then inherit a console that is already hidden, so CREATE_NO_WINDOW suppresses their windows the same way it does for a console-attached parent.

detached is left in place, so the #208 Ctrl+C process-group isolation is preserved — AllocConsole on a detached process is the documented escape hatch for exactly this situation.

Changes

  • build/windows-hidden-console.mjs (new): createHiddenConsole() wraps the AllocConsole / GetConsoleWindow / ShowWindow(SW_HIDE) koffi calls, best-effort (never blocks Harness startup), with an injectable loader for tests.
  • build/harness-node-entry.mjs: call createHiddenConsole() on Windows before the existing windowsHide child-process patch.
  • test/windows-hidden-console.test.ts (new): unit tests for the call sequence (alloc → hide with SW_HIDE), AllocConsole failure, null window, and loader-error fallbacks.

Validation

  • node --check passes on both changed build/*.mjs files.
  • createHiddenConsole logic exercised with a fake loader (alloc → hide with SW_HIDE=0; returns false on AllocConsole failure and on loader errors).
  • Not tested on a real Windows machine — the fix is Windows-only and this change was prepared on macOS; the full vitest suite was not run locally (no node_modules in this checkout). Please treat the console-flash behaviour as needing on-Windows confirmation.

Fixes #233

The desktop spawns the Harness with detached + windowsHide
(DETACHED_PROCESS | CREATE_NO_WINDOW), so the Harness itself has no
console. On Windows, a console child (pwsh, git, ripgrep, ...) spawned
from a console-less parent with only windowsHide (CREATE_NO_WINDOW)
still allocates a fresh, briefly-visible console — the flash reported on
every tool call in issue dataelement#233.

Attach a hidden console to the Harness at startup (AllocConsole +
ShowWindow(SW_HIDE)) so its children inherit a console that is already
hidden and CREATE_NO_WINDOW suppresses their windows the same way it
does for a console-attached parent. `detached` is left in place, so the
dataelement#208 Ctrl+C process-group isolation is preserved.

Fixes dataelement#233.
@yaojin3616
yaojin3616 merged commit fb168ef into dataelement:main Sep 4, 2026
bobowsh added a commit to bobowsh/dsh-desktop that referenced this pull request Sep 13, 2026
冲突决策:
- package.json: 依赖取上游 rc.1 tarball(244 deps);保留本地 chardet + dsh-llm-opencode fork;
  移除上游已删的 alpha.1 demo 包(spine-demo/tool-subagent-report);version 保持本地 0.3.2;
  build 脚本采纳上游 build:market,dev 保留本地 sync-harness-pkgs 前缀
- package-lock.json: 取上游 rc.1 lock 并对齐 version=0.3.2
- extraResources: 补打包 windows-hidden-console.mjs(上游 dataelement#289 entry 动态 import 但漏配打包)
- .gitignore: 合并(保留本地 data/ 注释块 + 上游 __pycache__)
- vitest.config.ts: 采纳上游 include 模式(test/**/test,spec.ts,js,mjs),兼容本地 .mjs 测试
- release.yml: 保留上游 prerelease/sign-windows job;两个 ModelScope step 均 if:false(本地 fork 无 token)
- 黑窗问题:采纳上游根因修复 createHiddenConsole(dataelement#289 AllocConsole+SW_HIDE),与本地
  enforceWindowsChildProcessHide(spawn 层 windowsHide) 在 harness-node-entry.mjs 共存双保险
- 保留本地特有:imc-region-capture 全屏截图桥、mobileBridge/ENABLE_MOBILE_BRIDGE、
  便携打包(bundle-user-data/installer.nsh extraFiles)、@earendil-works/pi-ai 补丁
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants