Skip to content

Commit f348284

Browse files
committed
fix(daemon): avoid workgroup schtasks user prompts
1 parent d92a333 commit f348284

2 files changed

Lines changed: 40 additions & 3 deletions

File tree

src/daemon/schtasks.install.test.ts

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,27 @@ describe("installScheduledTask", () => {
271271
});
272272
});
273273

274+
it("omits /RU for workgroup accounts so schtasks can use the current local user", async () => {
275+
await withUserProfileDir(async (_tmpDir, env) => {
276+
schtasksResponses.push(okSchtasksResponse, missingTaskResponse);
277+
278+
await installDefaultGatewayTask({
279+
...env,
280+
USERDOMAIN: "WORKGROUP",
281+
USERNAME: "alice",
282+
});
283+
284+
expectInitialTaskQueries();
285+
const createCall = schtasksCalls[2];
286+
expect(createCall?.slice(0, 5)).toEqual(["/Create", "/F", "/TN", "OpenClaw Gateway", "/XML"]);
287+
expect(createCall).not.toContain("/RU");
288+
const captured = xmlPayloadCaptures.find((entry) => entry.index === 2);
289+
expect(captured?.xml).toContain("<UserId>alice</UserId>");
290+
expect(captured?.xml).not.toContain("<GroupId>S-1-5-32-545</GroupId>");
291+
expectTaskRunCall(3);
292+
});
293+
});
294+
274295
it("re-applies the XML on /Change so upgraded tasks adopt battery flags (#59299)", async () => {
275296
await withUserProfileDir(async (_tmpDir, env) => {
276297
// /Query yes, /Query /TN yes, /Change ok, /Create /XML ok (upgrade), /Run ok.
@@ -296,7 +317,9 @@ describe("installScheduledTask", () => {
296317
const upgradeCapture = xmlPayloadCaptures.find((entry) => entry.index === 3);
297318
expect(upgradeCapture).toBeDefined();
298319
const upgradeXml = upgradeCapture?.xml ?? "";
299-
expect(upgradeXml).toContain("<DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>");
320+
expect(upgradeXml).toContain(
321+
"<DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>",
322+
);
300323
expect(upgradeXml).toContain("<StopIfGoingOnBatteries>false</StopIfGoingOnBatteries>");
301324
expectTaskRunCall(4);
302325
});

src/daemon/schtasks.ts

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -200,12 +200,25 @@ function resolveTaskUser(env: GatewayServiceEnv): string | null {
200200
return username;
201201
}
202202
const domain = env.USERDOMAIN;
203+
if (normalizeLowercaseStringOrEmpty(domain) === "workgroup") {
204+
return username;
205+
}
203206
if (domain) {
204207
return `${domain}\\${username}`;
205208
}
206209
return username;
207210
}
208211

212+
function resolveSchtasksCreateUser(env: GatewayServiceEnv, taskUser: string | null): string | null {
213+
// Workgroup hosts can report USERDOMAIN=WORKGROUP even though schtasks wants
214+
// the current local account. Keep the XML user-scoped, but omit /RU so
215+
// Task Scheduler binds the task to the caller instead of prompting.
216+
if (normalizeLowercaseStringOrEmpty(env.USERDOMAIN) === "workgroup") {
217+
return null;
218+
}
219+
return taskUser;
220+
}
221+
209222
function shouldUseHiddenWindowsTaskLauncher(env: GatewayServiceEnv): boolean {
210223
const value = normalizeLowercaseStringOrEmpty(env.OPENCLAW_WINDOWS_TASK_HIDDEN_LAUNCHER);
211224
return value === "1" || value === "true" || value === "yes";
@@ -1170,9 +1183,10 @@ async function activateScheduledTask(params: {
11701183
let create: Awaited<ReturnType<typeof execSchtasks>>;
11711184
try {
11721185
const xmlArgs = ["/Create", "/F", "/TN", taskName, "/XML", xmlPath];
1173-
const xmlArgsWithUser = taskUser ? [...xmlArgs, "/RU", taskUser, "/NP"] : xmlArgs;
1186+
const createUser = resolveSchtasksCreateUser(params.env, taskUser);
1187+
const xmlArgsWithUser = createUser ? [...xmlArgs, "/RU", createUser, "/NP"] : xmlArgs;
11741188
create = await execSchtasks(xmlArgsWithUser);
1175-
if (create.code !== 0 && taskUser) {
1189+
if (create.code !== 0 && createUser) {
11761190
// Retry without the elevated `/RU` form, matching the pre-XML behavior
11771191
// for accounts whose service password cannot be stored.
11781192
create = await execSchtasks(xmlArgs);

0 commit comments

Comments
 (0)