feat(worker): run worker as per-user logon task instead of Windows service
A LocalSystem Windows service can't see the logged-in user's Claude CLI authentication, so the worker now runs as the current user via a hidden per-user logon Scheduled Task with restart-on-failure. - Worker is WinExe (no console window) with a Serilog rolling file sink and a single-instance mutex so the logon task, app ensure-running, and Restart button can't fight over the SignalR port. - Installer replaces the service steps (register/start/stop) with autostart task steps, migrates the legacy ClaudeDoWorker service away on update, and removes the task on uninstall. ServicePage drops the service-account UI. - UI gains a WorkerLocator; the app ensures the worker is running at startup and the Restart button kills+relaunches this install's worker process. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -9,9 +9,9 @@ namespace ClaudeDo.Installer.Core;
|
||||
public sealed class UninstallRunner
|
||||
{
|
||||
private readonly InstallContext _context;
|
||||
private readonly StopServiceStep _stopService;
|
||||
private readonly StopWorkerStep _stopService;
|
||||
|
||||
public UninstallRunner(InstallContext context, StopServiceStep stopService)
|
||||
public UninstallRunner(InstallContext context, StopWorkerStep stopService)
|
||||
{
|
||||
_context = context;
|
||||
_stopService = stopService;
|
||||
@@ -27,16 +27,17 @@ public sealed class UninstallRunner
|
||||
// 2) Stop service. If stop fails we MUST abort — deleting a service whose
|
||||
// process is still running leaves orphan locked binaries under the install dir
|
||||
// which Directory.Delete will silently skip.
|
||||
progress.Report("Stopping worker service...");
|
||||
progress.Report("Stopping worker...");
|
||||
var stopResult = await _stopService.ExecuteAsync(_context, progress, ct);
|
||||
if (!stopResult.Success)
|
||||
return StepResult.Fail(
|
||||
$"Cannot uninstall: worker service did not stop cleanly. {stopResult.ErrorMessage} " +
|
||||
$"Cannot uninstall: worker did not stop cleanly. {stopResult.ErrorMessage} " +
|
||||
"Kill the worker manually and re-run uninstall.");
|
||||
|
||||
// 3) Unregister service.
|
||||
progress.Report("Unregistering service...");
|
||||
await ProcessRunner.RunAsync("sc.exe", $"delete {StopServiceStep.ServiceName}", null, progress, ct);
|
||||
// 3) Unregister the autostart task, and best-effort remove any legacy service.
|
||||
progress.Report("Removing autostart task...");
|
||||
await ProcessRunner.RunAsync("schtasks.exe", $"/Delete /TN \"{StopWorkerStep.TaskName}\" /F", null, progress, ct);
|
||||
await ProcessRunner.RunAsync("sc.exe", "delete ClaudeDoWorker", null, progress, ct);
|
||||
|
||||
// 3b) Remove Apps & Features registry entry (best-effort).
|
||||
progress.Report("Removing Add/Remove Programs entry...");
|
||||
|
||||
Reference in New Issue
Block a user