feat(installer): add UninstallRunner (service + shortcuts + dirs)
This commit is contained in:
@@ -121,6 +121,9 @@ public partial class App : Application
|
|||||||
sc.AddSingleton<StopServiceStep>();
|
sc.AddSingleton<StopServiceStep>();
|
||||||
sc.AddSingleton<StartServiceStep>();
|
sc.AddSingleton<StartServiceStep>();
|
||||||
|
|
||||||
|
// Runners
|
||||||
|
sc.AddSingleton<UninstallRunner>();
|
||||||
|
|
||||||
// ViewModels
|
// ViewModels
|
||||||
sc.AddSingleton<WizardViewModel>();
|
sc.AddSingleton<WizardViewModel>();
|
||||||
sc.AddSingleton<SettingsViewModel>();
|
sc.AddSingleton<SettingsViewModel>();
|
||||||
|
|||||||
68
src/ClaudeDo.Installer/Core/UninstallRunner.cs
Normal file
68
src/ClaudeDo.Installer/Core/UninstallRunner.cs
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
using System.IO;
|
||||||
|
using ClaudeDo.Data;
|
||||||
|
using ClaudeDo.Installer.Steps;
|
||||||
|
|
||||||
|
namespace ClaudeDo.Installer.Core;
|
||||||
|
|
||||||
|
public sealed class UninstallRunner
|
||||||
|
{
|
||||||
|
private readonly InstallContext _context;
|
||||||
|
private readonly StopServiceStep _stopService;
|
||||||
|
|
||||||
|
public UninstallRunner(InstallContext context, StopServiceStep stopService)
|
||||||
|
{
|
||||||
|
_context = context;
|
||||||
|
_stopService = stopService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<StepResult> RunAsync(IProgress<string> progress, CancellationToken ct)
|
||||||
|
{
|
||||||
|
// 1) Stop + delete service.
|
||||||
|
progress.Report("Stopping worker service...");
|
||||||
|
var stopResult = await _stopService.ExecuteAsync(_context, progress, ct);
|
||||||
|
if (!stopResult.Success)
|
||||||
|
{
|
||||||
|
progress.Report($"(Ignored) {stopResult.ErrorMessage}");
|
||||||
|
}
|
||||||
|
|
||||||
|
progress.Report("Unregistering service...");
|
||||||
|
await ProcessRunner.RunAsync("sc.exe", $"delete {StopServiceStep.ServiceName}", null, progress, ct);
|
||||||
|
|
||||||
|
// 2) Remove shortcuts.
|
||||||
|
progress.Report("Removing shortcuts...");
|
||||||
|
TryDeleteFile(Path.Combine(
|
||||||
|
Environment.GetFolderPath(Environment.SpecialFolder.CommonDesktopDirectory),
|
||||||
|
"ClaudeDo.lnk"));
|
||||||
|
TryDeleteFile(Path.Combine(
|
||||||
|
Environment.GetFolderPath(Environment.SpecialFolder.CommonStartMenu),
|
||||||
|
"Programs", "ClaudeDo.lnk"));
|
||||||
|
|
||||||
|
// 3) Delete install directory.
|
||||||
|
if (Directory.Exists(_context.InstallDirectory))
|
||||||
|
{
|
||||||
|
progress.Report($"Deleting {_context.InstallDirectory}...");
|
||||||
|
TryDeleteDir(_context.InstallDirectory);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4) Delete ~/.todo-app (config + DB + logs) — user opted into full removal.
|
||||||
|
var appData = Paths.AppDataRoot();
|
||||||
|
if (Directory.Exists(appData))
|
||||||
|
{
|
||||||
|
progress.Report($"Deleting {appData}...");
|
||||||
|
TryDeleteDir(appData);
|
||||||
|
}
|
||||||
|
|
||||||
|
progress.Report("Uninstall complete.");
|
||||||
|
return StepResult.Ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void TryDeleteFile(string path)
|
||||||
|
{
|
||||||
|
try { if (File.Exists(path)) File.Delete(path); } catch { /* best effort */ }
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void TryDeleteDir(string path)
|
||||||
|
{
|
||||||
|
try { Directory.Delete(path, recursive: true); } catch { /* best effort */ }
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user