release: prepare v2.0.53 updater handoff

Launch the verified NSIS installer directly before application shutdown, wait for Windows to confirm process creation, and keep the application open on spawn failure. Move process waiting into NSIS with a bounded graceful and post-force termination check, and cover the handoff with updater regression tests.
This commit is contained in:
Sucukdeluxe
2026-08-21 12:19:20 +02:00
parent c375491c88
commit bc86c29d57
8 changed files with 108 additions and 127 deletions
+9 -35
View File
@@ -896,35 +896,6 @@ async function resolveDigestFromYml(repo: string, tag: string, setupName: string
export function buildInstallerLaunchArgs(): string[] {
return ["/S", "--updated", "--force-run"];
}
function quotePowerShellLiteral(value: string): string {
return `'${value.replaceAll("'", "''")}'`;
}
export function buildDeferredInstallerLaunch(
targetPath: string,
currentProcessId: number = process.pid,
systemRoot: string = process.env.SystemRoot || "C:\\Windows"
): { command: string; args: string[] } {
const installerArgs = buildInstallerLaunchArgs().map(quotePowerShellLiteral).join(",");
const script = [
"$deadline=(Get-Date).AddMinutes(2)",
`while ((Get-Process -Id ${Math.max(1, Math.floor(currentProcessId))} -ErrorAction SilentlyContinue) -and ((Get-Date) -lt $deadline)) { Start-Sleep -Milliseconds 200 }`,
`Start-Process -FilePath ${quotePowerShellLiteral(targetPath)} -ArgumentList @(${installerArgs}) -WindowStyle Hidden`
].join("; ");
return {
command: path.win32.join(systemRoot, "System32", "WindowsPowerShell", "v1.0", "powershell.exe"),
args: [
"-NoLogo",
"-NoProfile",
"-NonInteractive",
"-WindowStyle",
"Hidden",
"-EncodedCommand",
Buffer.from(script, "utf16le").toString("base64")
]
};
}
export async function checkGitHubUpdate(repo: string): Promise<UpdateCheckResult> {
const safeRepo = normalizeUpdateRepo(repo);
@@ -1126,16 +1097,19 @@ export async function installLatestUpdate(
message: "Starte stille Update-Installation",
});
const deferredLaunch = buildDeferredInstallerLaunch(targetPath);
const child = childProcess.spawn(deferredLaunch.command, deferredLaunch.args, {
const child = childProcess.spawn(targetPath, buildInstallerLaunchArgs(), {
detached: true,
stdio: "ignore",
windowsHide: true,
});
child.once("error", (spawnError) => {
logger.error(`Update-Launcher Start fehlgeschlagen: ${compactErrorText(spawnError)}`);
});
child.unref();
await new Promise<void>((resolve, reject) => {
child.once("spawn", resolve);
child.once("error", (spawnError) => {
logger.error(`Update-Installer Start fehlgeschlagen: ${compactErrorText(spawnError)}`);
reject(spawnError);
});
});
child.unref();
emitProgress(onProgress, {
stage: "done", percent: 100, downloadedBytes: 0, totalBytes: null,