diff --git a/src/ClaudeDo.Installer/Core/ScheduledTaskXml.cs b/src/ClaudeDo.Installer/Core/ScheduledTaskXml.cs
deleted file mode 100644
index 7d0cc80..0000000
--- a/src/ClaudeDo.Installer/Core/ScheduledTaskXml.cs
+++ /dev/null
@@ -1,52 +0,0 @@
-using System.Security;
-
-namespace ClaudeDo.Installer.Core;
-
-public static class ScheduledTaskXml
-{
- public static string Build(string userId, string workerExePath, int restartIntervalMinutes)
- {
- var minutes = restartIntervalMinutes < 1 ? 1 : restartIntervalMinutes;
- var user = SecurityElement.Escape(userId);
- var cmd = SecurityElement.Escape(workerExePath);
- return $"""
-
-
-
- ClaudeDo background worker (per-user).
-
-
-
- true
- {user}
-
-
-
-
- {user}
- InteractiveToken
- LeastPrivilege
-
-
-
- IgnoreNew
- false
- false
- true
- true
- true
- PT0S
-
- PT{minutes}M
- 3
-
-
-
-
- {cmd}
-
-
-
- """;
- }
-}
diff --git a/src/ClaudeDo.Installer/Steps/RegisterAutostartStep.cs b/src/ClaudeDo.Installer/Steps/RegisterAutostartStep.cs
index 0580c3a..359d941 100644
--- a/src/ClaudeDo.Installer/Steps/RegisterAutostartStep.cs
+++ b/src/ClaudeDo.Installer/Steps/RegisterAutostartStep.cs
@@ -1,12 +1,11 @@
using System.IO;
-using System.Security.Principal;
using ClaudeDo.Installer.Core;
namespace ClaudeDo.Installer.Steps;
public sealed class RegisterAutostartStep : IInstallStep
{
- public const string TaskName = "ClaudeDoWorker";
+ public const string LegacyTaskName = "ClaudeDoWorker";
private const string LegacyServiceName = "ClaudeDoWorker";
public string Name => "Register Autostart";
@@ -34,24 +33,19 @@ public sealed class RegisterAutostartStep : IInstallStep
}
}
- // 2) Register (or replace) the per-user logon task.
- var userId = WindowsIdentity.GetCurrent().Name;
- var minutes = Math.Max(1, ctx.RestartDelayMs / 60000);
- var xml = ScheduledTaskXml.Build(userId, workerExe, minutes);
+ // 2) Migrate away the legacy logon scheduled task if present (best-effort).
+ progress.Report("Removing legacy logon task...");
+ await ProcessRunner.RunAsync("schtasks.exe", $"/Delete /TN \"{LegacyTaskName}\" /F", null, progress, ct);
- var xmlPath = Path.Combine(Path.GetTempPath(), $"ClaudeDoWorker-{Guid.NewGuid():N}.xml");
- await File.WriteAllTextAsync(xmlPath, xml, new System.Text.UnicodeEncoding(false, true), ct);
+ // 3) Register per-user autostart via a Startup-folder shortcut.
+ progress.Report("Creating Startup shortcut...");
try
{
- progress.Report("Registering logon task...");
- var (exit, output) = await ProcessRunner.RunAsync(
- "schtasks.exe", $"/Create /TN \"{TaskName}\" /XML \"{xmlPath}\" /F", null, progress, ct);
- if (exit != 0)
- return StepResult.Fail($"schtasks /Create failed (exit {exit}): {output}");
+ AutostartShortcut.Install(AutostartShortcut.DefaultStartupDir, workerExe);
}
- finally
+ catch (Exception ex)
{
- try { File.Delete(xmlPath); } catch { /* best effort */ }
+ return StepResult.Fail($"Failed to create Startup shortcut: {ex.Message}");
}
return StepResult.Ok();
diff --git a/tests/ClaudeDo.Installer.Tests/ScheduledTaskXmlTests.cs b/tests/ClaudeDo.Installer.Tests/ScheduledTaskXmlTests.cs
deleted file mode 100644
index 7bfa994..0000000
--- a/tests/ClaudeDo.Installer.Tests/ScheduledTaskXmlTests.cs
+++ /dev/null
@@ -1,30 +0,0 @@
-using ClaudeDo.Installer.Core;
-
-namespace ClaudeDo.Installer.Tests;
-
-public class ScheduledTaskXmlTests
-{
- [Fact]
- public void Build_EmbedsUserExeAndLogonTrigger()
- {
- var xml = ScheduledTaskXml.Build(
- userId: "MACHINE\\mika",
- workerExePath: @"C:\Program Files\ClaudeDo\worker\ClaudeDo.Worker.exe",
- restartIntervalMinutes: 1);
-
- Assert.Contains("", xml);
- Assert.Contains("MACHINE\\mika", xml);
- Assert.Contains("InteractiveToken", xml);
- Assert.Contains("true", xml);
- Assert.Contains("LeastPrivilege", xml);
- Assert.Contains(@"C:\Program Files\ClaudeDo\worker\ClaudeDo.Worker.exe", xml);
- Assert.Contains("PT1M", xml);
- }
-
- [Fact]
- public void Build_ClampsRestartIntervalToOneMinuteMinimum()
- {
- var xml = ScheduledTaskXml.Build("M\\u", @"C:\w.exe", restartIntervalMinutes: 0);
- Assert.Contains("PT1M", xml);
- }
-}