Compare commits

...
Author SHA1 Message Date
Cursor Agentand陈大猫 36931f938b fix(win): kill leftover Netcatty.exe before NSIS install (#3946)
Orphaned external MCP servers stay alive as Netcatty.exe launched with
ELECTRON_RUN_AS_NODE=1 and lock the install directory, so the in-app
updater hangs. Force-kill that image from NSIS customInit before files
are replaced, without /T so the installer itself is not killed.

Co-authored-by: 陈大猫 <binaricat@users.noreply.github.com>
2026-10-26 08:18:45 +00:00
2 changed files with 31 additions and 0 deletions

No files matched your search

+11
View File
@@ -1,3 +1,14 @@
!macro customInit
; #3946: external MCP hosts launch Netcatty.exe with ELECTRON_RUN_AS_NODE=1
; via netcatty-external-mcp.cmd. Those processes can outlive the host UI as
; orphans and keep $INSTDIR locked, so the in-app updater hangs (AppHangB1).
; Force-kill leftover Netcatty.exe before files are replaced. Do not pass /T:
; electron-updater spawns this installer as a child of the UI Netcatty.exe,
; and /T would terminate the installer itself. Ignore a missing process.
nsExec::ExecToLog "taskkill /F /IM Netcatty.exe"
Pop $0
!macroend
!macro customInstall
; Open a selected folder in a new Netcatty local terminal.
; Args go after `--` so Electron/Chromium does not swallow them. Use
+20
View File
@@ -345,6 +345,26 @@ test("windows packaging includes a zip archive target", () => {
);
});
test("windows installer kills leftover Netcatty.exe before file replacement", () => {
const fs = require("node:fs");
const path = require("node:path");
const installerScript = fs.readFileSync(
path.join(__dirname, "..", config.nsis.include),
"utf8",
);
assert.match(installerScript, /!macro customInit\b/);
assert.match(installerScript, /#3946/);
assert.match(installerScript, /ELECTRON_RUN_AS_NODE/);
assert.match(
installerScript,
/nsExec::ExecToLog "taskkill \/F \/IM Netcatty\.exe"/,
);
assert.match(installerScript, /Pop \$0/);
// /T would kill this installer while it is still a child of the UI Netcatty.exe.
assert.doesNotMatch(installerScript, /taskkill [^\r\n]*\/T/);
});
test("windows installer registers and removes Explorer folder context menu entries", () => {
const fs = require("node:fs");
const path = require("node:path");