cicy-desktop 2.1.337 → 2.1.338
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
package/src/app-updater.js
CHANGED
|
@@ -340,30 +340,41 @@ async function downloadUpdate() {
|
|
|
340
340
|
|
|
341
341
|
// 用户点「安装」:拉起原生安装器(win NSIS / mac pkg)并退出 app;linux AppImage 在
|
|
342
342
|
// 文件管理器里定位(AppImage 非安装器,用户自行替换运行)。
|
|
343
|
-
// Windows install + relaunch, as
|
|
343
|
+
// Windows install + relaunch, as one hidden chain.
|
|
344
344
|
//
|
|
345
345
|
// shell.openPath() ran the NSIS installer INTERACTIVELY: on a machine with
|
|
346
346
|
// nobody at the keyboard that is a wizard waiting forever for a click, and even
|
|
347
347
|
// when it did install, nothing started the app again — NSIS runAfterFinish does
|
|
348
348
|
// not fire on a /S install. Both together are why an unattended node that took
|
|
349
|
-
// an update
|
|
350
|
-
//
|
|
349
|
+
// an update never came back; it had to be started by hand, and a headless box
|
|
350
|
+
// has no hand.
|
|
351
351
|
//
|
|
352
|
-
//
|
|
353
|
-
//
|
|
354
|
-
//
|
|
355
|
-
//
|
|
352
|
+
// The chain must also be INVISIBLE. Doing it with spawn(detached:true) put a
|
|
353
|
+
// black console on screen counting down for 20 seconds during every update:
|
|
354
|
+
// on Windows `detached` means CREATE_NEW_CONSOLE, which windowsHide cannot
|
|
355
|
+
// suppress. So it goes through wscript + a one-line VBS with window style 0 —
|
|
356
|
+
// the same hidden-launch trick writeSourceAutostartVbs() already uses — which
|
|
357
|
+
// is genuinely windowless and detached from this process either way.
|
|
356
358
|
function installWindows(installer) {
|
|
357
359
|
const { spawn } = require("child_process");
|
|
358
360
|
const exe = process.execPath;
|
|
359
|
-
const
|
|
360
|
-
|
|
361
|
+
const dir = path.join(process.env.LOCALAPPDATA || os.homedir(), "cicy-desktop");
|
|
362
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
363
|
+
const vbs = path.join(dir, "update-install.vbs");
|
|
364
|
+
// VBS escapes a double quote by doubling it. cmd waits for the installer (no
|
|
365
|
+
// `start` on that leg), then the pause lets Windows release the replaced
|
|
366
|
+
// files before the new exe runs hidden.
|
|
367
|
+
const cmd =
|
|
368
|
+
`cmd /c ""${installer}" /S & timeout /t 20 /nobreak >nul & start "" "${exe}" --hidden"`;
|
|
369
|
+
const line = `sh.Run "${cmd.replace(/"/g, '""')}", 0, False`;
|
|
370
|
+
fs.writeFileSync(vbs, ['Set sh = CreateObject("WScript.Shell")', line, ""].join("\r\n"));
|
|
371
|
+
const ch = spawn("wscript.exe", ["//B", "//Nologo", vbs], {
|
|
361
372
|
detached: true,
|
|
362
373
|
stdio: "ignore",
|
|
363
374
|
windowsHide: true,
|
|
364
375
|
});
|
|
365
376
|
ch.unref();
|
|
366
|
-
log.info(`[app-updater]
|
|
377
|
+
log.info(`[app-updater] hidden install + relaunch chain started (pid ${ch.pid})`);
|
|
367
378
|
// Quit so the installer can replace the files it is about to overwrite.
|
|
368
379
|
setTimeout(() => { try { app.quit(); } catch {} }, 1500);
|
|
369
380
|
}
|
|
@@ -26,6 +26,17 @@ test("windows installs silently instead of opening a wizard nobody can click", (
|
|
|
26
26
|
);
|
|
27
27
|
});
|
|
28
28
|
|
|
29
|
+
test("the chain is windowless — no console flashes during an update", () => {
|
|
30
|
+
// Regression: doing this with spawn(detached:true) put a black console on
|
|
31
|
+
// screen counting down for 20s on every update. On Windows `detached` means
|
|
32
|
+
// CREATE_NEW_CONSOLE, which windowsHide cannot suppress, so the runner has to
|
|
33
|
+
// be wscript + a window-style-0 VBS (same trick as writeSourceAutostartVbs).
|
|
34
|
+
assert.match(win, /spawn\("wscript\.exe", \["\/\/B", "\/\/Nologo", vbs\]/);
|
|
35
|
+
assert.match(win, /sh\.Run "\$\{cmd\.replace\(\/"\/g, '""'\)\}", 0, False/);
|
|
36
|
+
assert.match(win, /CreateObject\("WScript\.Shell"\)/);
|
|
37
|
+
assert.doesNotMatch(win, /spawn\(process\.env\.COMSPEC/); // the visible-console version
|
|
38
|
+
});
|
|
39
|
+
|
|
29
40
|
test("the relaunch is part of the same detached chain, so it outlives the app", () => {
|
|
30
41
|
// The installer kills this process; a child in this process group would die
|
|
31
42
|
// with it and the machine would stay down.
|