Skip to content

Windows: resolveGitBranch() spawns git without windowsHide — a terminal window flashes on every conversation switch #259

Description

@EvenZ2001

提交前查重 / Duplicate check

  • 我已搜索 open/closed Issue,确认没有重复。 / I searched open and closed issues and found no duplicate.

本仓库此前无 Windows 控制台窗口相关的报告。相关(但主题不同):#5(Windows CLI discovery)。

涉及区域 / Affected area

  • 运行时记忆 / Runtime Memory

Issue 类型 / Issue type

Bug 报告 / Bug report

摘要 / Summary

在 Windows 上,resolveGitBranch() 调用 execFileSync('git', …) 时未传 windowsHide: true。当 DSH 宿主是无控制台的 GUI 进程(DSH Desktop / Electron)时,Windows 会为每次调用新建一个可见的控制台窗口,表现为一个 Windows Terminal 窗口闪现后立刻消失。由于该函数位于会话投影(session projection)路径上,因此每次切换/加载对话都会闪一次窗口。

预期结果 / Expected outcome

  • 切换对话、加载会话或执行 git 分支探测时,不出现任何终端/控制台窗口。
  • resolveGitBranch() 的行为(返回值、超时、失败时回退到未过滤视图)完全不变。
  • 在非 Windows 平台上行为不变(windowsHide 在 POSIX 上是 no-op)。

详情或复现步骤 / Details or reproduction steps

受影响文件: plugins/dsh-mnemon-source-runtime/src/git-branch.ts

const output = execFileSync('git', ['-C', root, 'branch', '--show-current'], {
  encoding: 'utf8',
  timeout: GIT_BRANCH_TIMEOUT_MS,
  stdio: ['ignore', 'pipe', 'ignore'],
  // ← 缺少 windowsHide: true
})

调用点(会话投影,src/index.ts):

const projection = (workspaceId) => controller.contextProjection(resolveGitBranch(workspaceId))

复现步骤:

  1. 在 DSH Desktop(Windows 11,默认终端宿主为 Windows Terminal)上安装 dsh-mnemon。
  2. 在同一个 git 仓库工作区中至少打开两个对话。
  3. 在侧边栏中来回点击切换对话。
  4. 实际结果: 每次切换都有一个终端窗口闪现并立即关闭。
  5. 预期结果: 无窗口;git 探测应对用户完全不可见。

根因说明:

当父进程没有控制台、且未传 CREATE_NO_WINDOW 时,CreateProcess 会为控制台子系统的子进程新建一个可见控制台。windowsHide: true 正是让 Node 传递 CREATE_NO_WINDOW 的开关。本项目其余 spawn 调用(如 dsh-mnemon/lib/index.js:6072、dsh-mnemon-source-memory-spaces/lib/process-BvrgxPNP.js:18)均已正确设置该标志,仅此处遗漏。

环境信息 / Environment

  • DSH 版本 / DSH version: DSH Desktop 2.0.10
  • dsh-mnemon 版本或 commit / dsh-mnemon version or commit: 0.5.10
  • dsh-mnemon-source-runtime 版本 / version: 0.5.7
  • Mnemon 版本 / Mnemon version: @mnemon-dev/mnemon 0.2.8
  • Node.js / pnpm: DSH Desktop 内置 Node(Electron)
  • 操作系统或浏览器 / OS or browser: Windows 11 教育版 10.0.26200(Windows Terminal 1.24.11911.0,Win11 默认终端宿主)
  • Provider 或相关配置(已脱敏)/ Provider or related configuration (redacted): N/A(与本问题无关)
  • git 版本: 2.53.0.windows.1(D:\Git\cmd\git.exe)

Bug 证据 / Bug evidence

对照实验(A/B),从无控制台的父进程(pythonw.exe)spawn git --version,同时用 EnumWindows 枚举窗口:

不加 windowsHide(当前代码):

NEW terminal windows: 2
  class=CASCADIA_HOSTING_WINDOW_CLASS visible=True pid=2772  title='D:\\Git\\cmd\\git.exe'
  class=PseudoConsoleWindow              visible=True pid=19800 title=''

加上 windowsHide: true:

NEW terminal windows: 0
  (no window: child ran without a visible console)

同路径的进程创建链(可见窗口正是由这条链产生):

git.exe
  → conhost.exe 0x4
    → OpenConsole.exe -Embedding
      → WindowsTerminal.exe -Embedding   ← 用户看到的闪现窗口

前台窗口轮询(每 80 ms 取一次 GetForegroundWindow)直接抓到了闪现:

FOCUS -> WindowsTerminal [...|CASCADIA_HOSTING_WINDOW_CLASS|...\mnemon-win32-x64\bin\mnemon.exe]

冒烟测试 / Smoke test

  • 测试环境 / Test environment: Windows 11 10.0.26200,DSH Desktop 2.0.10,Windows Terminal 为默认终端宿主
  • 执行命令或操作 / Commands or actions: 在已安装的 lib/index.js 打上补丁后,重新导入模块并连续执行会话投影路径 4 次
  • 实际结果 / Observed result: 新增终端窗口数 = 0(打补丁前每次运行 1 个)
  • 对照版本或配置 / Control version or configuration: 未打补丁的 execFileSync,同一环境下每次运行均产生 1 个可见窗口

引用代码 / Code references

  • plugins/dsh-mnemon-source-runtime/src/git-branch.ts(resolveGitBranch)
  • plugins/dsh-mnemon-source-runtime/src/index.ts(projection 调用点)

补丁草案 / Patch proposal

--- a/plugins/dsh-mnemon-source-runtime/src/git-branch.ts
+++ b/plugins/dsh-mnemon-source-runtime/src/git-branch.ts
@@
     const output = execFileSync('git', ['-C', root, 'branch', '--show-current'], {
       encoding: 'utf8',
       timeout: GIT_BRANCH_TIMEOUT_MS,
+      windowsHide: true,
       stdio: ['ignore', 'pipe', 'ignore'],
     })

windowsHide 在 POSIX 上是文档化的 no-op,因此可无条件添加。

补充信息 / Additional context

  • @mnemon-dev/mnemon 的 npm CLI 包装器(lib/child.js)存在同类问题,因属于另一上游仓库,已单独报告至 mnemon-dev/mnemon#143。
  • 这是 Windows 上观感明显但非致命的缺陷:它在每次切换对话时触发,正常使用中极易察觉。
  • 建议顺带考虑加一条 CI/lint 守卫:断言 Windows 上每个 spawn/execFile/spawnSync 调用点都传入 windowsHide,以防此类回归。

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions