






















@@ -100,9 +100,10 @@ function resolveStartupEntryPath(env: GatewayServiceEnv, extension?: "cmd" | "vb
100100function resolveStartupEntryPaths(env: GatewayServiceEnv): string[] {
101101const primaryPath = resolveStartupEntryPath(env);
102102const legacyCmdPath = resolveStartupEntryPath(env, "cmd");
103-// Hidden VBS launchers supersede cmd launchers, but uninstall must remove the
104-// legacy cmd path from older installs too.
105-return uniqueStrings([primaryPath, legacyCmdPath]);
103+const hiddenLauncherPath = resolveStartupEntryPath(env, "vbs");
104+// Hidden VBS launchers supersede cmd launchers, but lifecycle operations must
105+// discover both variants even when the caller env lacks the persisted marker.
106+return uniqueStrings([primaryPath, legacyCmdPath, hiddenLauncherPath]);
106107}
107108108109// `/TR` is parsed by schtasks itself, while the generated `gateway.cmd` line is parsed by cmd.exe.
@@ -923,6 +924,70 @@ async function restartStartupEntry(
923924return { outcome: "completed" };
924925}
925926927+const CALLER_OWNED_SERVICE_IDENTITY_KEYS = [
928+"OPENCLAW_LAUNCHD_LABEL",
929+"OPENCLAW_SYSTEMD_UNIT",
930+"OPENCLAW_WINDOWS_TASK_NAME",
931+] as const;
932+933+function resolveScheduledTaskRenderEnv(
934+env: GatewayServiceEnv,
935+environment: GatewayServiceEnv | undefined,
936+): GatewayServiceEnv {
937+if (!environment) {
938+return env;
939+}
940+const merged = { ...env, ...environment };
941+for (const key of CALLER_OWNED_SERVICE_IDENTITY_KEYS) {
942+const value = env[key]?.trim();
943+if (value) {
944+merged[key] = value;
945+}
946+}
947+return merged;
948+}
949+950+function resolveScheduledTaskScriptEnvironment(
951+taskEnv: GatewayServiceEnv,
952+environment: GatewayServiceEnv | undefined,
953+): GatewayServiceEnv | undefined {
954+const scriptEnv = environment ? { ...environment } : {};
955+for (const key of CALLER_OWNED_SERVICE_IDENTITY_KEYS) {
956+const value = taskEnv[key]?.trim();
957+if (value) {
958+scriptEnv[key] = value;
959+}
960+}
961+return Object.keys(scriptEnv).length > 0 ? scriptEnv : undefined;
962+}
963+964+const SCHEDULED_TASK_ACTIVATION_KEYS = [
965+"OPENCLAW_WINDOWS_TASK_HIDDEN_LAUNCHER",
966+"OPENCLAW_TASK_SCRIPT_NAME",
967+"OPENCLAW_TASK_SCRIPT",
968+"OPENCLAW_SERVICE_KIND",
969+"OPENCLAW_GATEWAY_PORT",
970+"OPENCLAW_STATE_DIR",
971+"OPENCLAW_PROFILE",
972+] as const;
973+974+function resolveScheduledTaskActivationEnv(
975+env: GatewayServiceEnv,
976+environment: GatewayServiceEnv | undefined,
977+): GatewayServiceEnv {
978+if (!environment) {
979+return env;
980+}
981+const activationEnv = { ...env };
982+for (const key of SCHEDULED_TASK_ACTIVATION_KEYS) {
983+const value = environment[key];
984+if (value !== undefined) {
985+activationEnv[key] = value;
986+}
987+}
988+return activationEnv;
989+}
990+926991async function writeScheduledTaskScript({
927992 env,
928993 programArguments,
@@ -933,17 +998,24 @@ async function writeScheduledTaskScript({
933998scriptPath: string;
934999taskLaunchPath: string;
9351000taskDescription: string;
1001+taskEnv: GatewayServiceEnv;
9361002}> {
9371003await assertSchtasksAvailable().catch(() => undefined);
938-const scriptPath = resolveTaskScriptPath(env);
939-const taskLaunchPath = resolveTaskLauncherScriptPath(env, scriptPath);
1004+const taskEnv = resolveScheduledTaskRenderEnv(env, environment);
1005+const scriptPath = resolveTaskScriptPath(taskEnv);
1006+const taskLaunchPath = resolveTaskLauncherScriptPath(taskEnv, scriptPath);
9401007await fs.mkdir(path.dirname(scriptPath), { recursive: true });
941-const taskDescription = resolveGatewayServiceDescription({ env, environment, description });
1008+const taskDescription = resolveGatewayServiceDescription({
1009+env: taskEnv,
1010+ environment,
1011+ description,
1012+});
1013+const scriptEnvironment = resolveScheduledTaskScriptEnvironment(taskEnv, environment);
9421014const script = buildTaskScript({
9431015description: taskDescription,
9441016 programArguments,
9451017 workingDirectory,
946- environment,
1018+environment: scriptEnvironment,
9471019});
9481020await fs.writeFile(scriptPath, script, "utf8");
9491021if (taskLaunchPath !== scriptPath) {
@@ -953,7 +1025,7 @@ async function writeScheduledTaskScript({
9531025});
9541026await fs.writeFile(taskLaunchPath, launcher, "utf8");
9551027}
956-return { scriptPath, taskLaunchPath, taskDescription };
1028+return { scriptPath, taskLaunchPath, taskDescription, taskEnv };
9571029}
95810309591031export async function stageScheduledTask({
@@ -1243,7 +1315,7 @@ export async function installScheduledTask(
12431315): Promise<{ scriptPath: string }> {
12441316const staged = await writeScheduledTaskScript(args);
12451317await activateScheduledTask({
1246-env: args.env,
1318+env: resolveScheduledTaskActivationEnv(args.env, args.environment),
12471319stdout: args.stdout,
12481320scriptPath: staged.scriptPath,
12491321taskLaunchPath: staged.taskLaunchPath,
@@ -1271,8 +1343,15 @@ export async function uninstallScheduledTask({
12711343}
1272134412731345const scriptPath = resolveTaskScriptPath(env);
1274-const launcherPath = resolveTaskLauncherScriptPath(env, scriptPath);
1275-if (launcherPath !== scriptPath) {
1346+const parsedScriptPath = path.parse(scriptPath);
1347+const launcherPaths = uniqueStrings([
1348+resolveTaskLauncherScriptPath(env, scriptPath),
1349+path.join(parsedScriptPath.dir, `${parsedScriptPath.name}.vbs`),
1350+]);
1351+for (const launcherPath of launcherPaths) {
1352+if (launcherPath === scriptPath) {
1353+continue;
1354+}
12761355try {
12771356await fs.unlink(launcherPath);
12781357stdout.write(`${formatLine("Removed task launcher", launcherPath)}\n`);
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。