Skip to content

Commit e1b40c4

Browse files
committed
fix: remove duplicate restart messages in Windows scheduled task restart
1 parent 5d815b2 commit e1b40c4

1 file changed

Lines changed: 51 additions & 11 deletions

File tree

src/daemon/schtasks.ts

Lines changed: 51 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { findVerifiedGatewayListenerPidsOnPortSync } from "../infra/gateway-proc
66
import { inspectPortUsage } from "../infra/ports.js";
77
import { getWindowsInstallRoots } from "../infra/windows-install-roots.js";
88
import { killProcessTree } from "../process/kill-tree.js";
9+
import { normalizeLowercaseStringOrEmpty } from "../shared/string-coerce.js";
910
import { sleep } from "../utils.js";
1011
import { parseCmdScriptCommandLine, quoteCmdScriptArg } from "./cmd-argv.js";
1112
import { assertNoCmdLineBreak, parseCmdSetAssignment, renderCmdSetAssignment } from "./cmd-set.js";
@@ -121,7 +122,7 @@ export async function readScheduledTaskCommand(
121122
if (!line) {
122123
continue;
123124
}
124-
const lower = line.toLowerCase();
125+
const lower = normalizeLowercaseStringOrEmpty(line);
125126
if (line.startsWith("@echo")) {
126127
continue;
127128
}
@@ -192,7 +193,7 @@ function normalizeTaskResultCode(value?: string): string | null {
192193
if (!value) {
193194
return null;
194195
}
195-
const raw = value.trim().toLowerCase();
196+
const raw = normalizeLowercaseStringOrEmpty(value);
196197
if (!raw) {
197198
return null;
198199
}
@@ -542,7 +543,6 @@ async function restartStartupEntry(
542543
await terminateGatewayProcessTree(runtime.pid, 300);
543544
}
544545
launchFallbackTaskScript(resolveTaskScriptPath(env));
545-
stdout.write(`${formatLine("Restarted Windows login item", resolveTaskName(env))}\n`);
546546
return { outcome: "completed" };
547547
}
548548

@@ -581,6 +581,45 @@ export async function stageScheduledTask({
581581
return { scriptPath };
582582
}
583583

584+
async function updateExistingScheduledTask(params: {
585+
env: GatewayServiceEnv;
586+
stdout: NodeJS.WritableStream;
587+
taskName: string;
588+
quotedScript: string;
589+
scriptPath: string;
590+
}): Promise<boolean> {
591+
if (!(await isRegisteredScheduledTask(params.env))) {
592+
return false;
593+
}
594+
const change = await execSchtasks([
595+
"/Change",
596+
"/TN",
597+
params.taskName,
598+
"/TR",
599+
params.quotedScript,
600+
]);
601+
if (change.code !== 0) {
602+
return false;
603+
}
604+
await runScheduledTaskOrThrow(params.taskName);
605+
writeFormattedLines(
606+
params.stdout,
607+
[
608+
{ label: "Updated Scheduled Task", value: params.taskName },
609+
{ label: "Task script", value: params.scriptPath },
610+
],
611+
{ leadingBlankLine: true },
612+
);
613+
return true;
614+
}
615+
616+
async function runScheduledTaskOrThrow(taskName: string): Promise<void> {
617+
const run = await execSchtasks(["/Run", "/TN", taskName]);
618+
if (run.code !== 0) {
619+
throw new Error(`schtasks run failed: ${run.stderr || run.stdout}`.trim());
620+
}
621+
}
622+
584623
async function activateScheduledTask(params: {
585624
env: GatewayServiceEnv;
586625
stdout: NodeJS.WritableStream;
@@ -591,6 +630,11 @@ async function activateScheduledTask(params: {
591630

592631
const taskName = resolveTaskName(params.env);
593632
const quotedScript = quoteSchtasksArg(params.scriptPath);
633+
634+
if (await updateExistingScheduledTask({ ...params, taskName, quotedScript })) {
635+
return;
636+
}
637+
594638
const baseArgs = [
595639
"/Create",
596640
"/F",
@@ -634,7 +678,7 @@ async function activateScheduledTask(params: {
634678
throw new Error(`schtasks create failed: ${detail}`.trim());
635679
}
636680

637-
await execSchtasks(["/Run", "/TN", taskName]);
681+
await runScheduledTaskOrThrow(taskName);
638682
// Ensure we don't end up writing to a clack spinner line (wizards show progress without a newline).
639683
writeFormattedLines(
640684
params.stdout,
@@ -686,7 +730,7 @@ export async function uninstallScheduledTask({
686730
}
687731

688732
function isTaskNotRunning(res: { stdout: string; stderr: string; code: number }): boolean {
689-
const detail = (res.stderr || res.stdout).toLowerCase();
733+
const detail = normalizeLowercaseStringOrEmpty(res.stderr || res.stdout);
690734
return detail.includes("not running");
691735
}
692736

@@ -761,11 +805,7 @@ export async function restartScheduledTask({
761805
}
762806
}
763807
}
764-
const res = await execSchtasks(["/Run", "/TN", taskName]);
765-
if (res.code !== 0) {
766-
throw new Error(`schtasks run failed: ${res.stderr || res.stdout}`.trim());
767-
}
768-
stdout.write(`${formatLine("Restarted Scheduled Task", taskName)}\n`);
808+
await runScheduledTaskOrThrow(taskName);
769809
return { outcome: "completed" };
770810
}
771811

@@ -798,7 +838,7 @@ export async function readScheduledTaskRuntime(
798838
return await resolveFallbackRuntime(env);
799839
}
800840
const detail = (res.stderr || res.stdout).trim();
801-
const missing = detail.toLowerCase().includes("cannot find the file");
841+
const missing = normalizeLowercaseStringOrEmpty(detail).includes("cannot find the file");
802842
return {
803843
status: missing ? "stopped" : "unknown",
804844
detail: detail || undefined,

0 commit comments

Comments
 (0)