RegisterAutostartStep rewrote the Startup .lnk on every install/update/repair even when it already pointed at the right worker exe. AutostartShortcut.Install now reads the existing shortcut's target via ShortcutFactory.TryGetTarget and skips the rewrite when it matches, reporting the skip in progress output. Legacy service/scheduled-task cleanup stays unconditional (migration safety net).
60 lines
2.7 KiB
C#
60 lines
2.7 KiB
C#
using System.IO;
|
|
using ClaudeDo.Installer.Core;
|
|
|
|
namespace ClaudeDo.Installer.Steps;
|
|
|
|
public sealed class RegisterAutostartStep : IInstallStep
|
|
{
|
|
public const string LegacyTaskName = "ClaudeDoWorker";
|
|
private const string LegacyServiceName = "ClaudeDoWorker";
|
|
|
|
public string Name => "Register Autostart";
|
|
|
|
public async Task<StepResult> ExecuteAsync(InstallContext ctx, IProgress<string> progress, CancellationToken ct)
|
|
{
|
|
var workerExe = Path.Combine(ctx.InstallDirectory, "worker", "ClaudeDo.Worker.exe");
|
|
if (!File.Exists(workerExe))
|
|
return StepResult.Fail($"Worker executable not found: {workerExe}");
|
|
|
|
// Legacy service/task cleanup below runs unconditionally on every install/update/repair,
|
|
// even though it's a no-op once migrated. A cached "already migrated" flag could go stale
|
|
// (e.g. a user re-adds the legacy service) and strand them with it still running; two
|
|
// extra process starts per run is the price for that migration safety net.
|
|
|
|
// 1) Migrate away the legacy Windows service if present.
|
|
progress.Report("Checking for legacy worker service...");
|
|
var (queryExit, _) = await ProcessRunner.RunAsync("sc.exe", $"query {LegacyServiceName}", null, progress, ct);
|
|
if (queryExit == 0)
|
|
{
|
|
progress.Report("Removing legacy worker service...");
|
|
await ProcessRunner.RunAsync("sc.exe", $"stop {LegacyServiceName}", null, progress, ct);
|
|
await ProcessRunner.RunAsync("sc.exe", $"delete {LegacyServiceName}", null, progress, ct);
|
|
for (var i = 0; i < 30; i++)
|
|
{
|
|
ct.ThrowIfCancellationRequested();
|
|
var (q, _) = await ProcessRunner.RunAsync("sc.exe", $"query {LegacyServiceName}", null, progress, ct);
|
|
if (q != 0) break;
|
|
await Task.Delay(1000, ct);
|
|
}
|
|
}
|
|
|
|
// 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);
|
|
|
|
// 3) Register per-user autostart via a Startup-folder shortcut.
|
|
progress.Report("Checking Startup shortcut...");
|
|
try
|
|
{
|
|
var created = AutostartShortcut.Install(AutostartShortcut.DefaultStartupDir, workerExe);
|
|
progress.Report(created ? "Startup shortcut created." : "Startup shortcut already up to date.");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
return StepResult.Fail($"Failed to create Startup shortcut: {ex.Message}");
|
|
}
|
|
|
|
return StepResult.Ok();
|
|
}
|
|
}
|