IBaseDirtyChecker, IInteractiveLaunchSpecService and the LaunchSpec wrapper had one implementation and one caller each; ProcessRunnerAdapter existed only to give a static class an interface, and InstallArtifactLocator used inheritance for two constructor arguments. The external MCP container now shares its singletons through a Share<T> helper instead of 17 near-identical registrations.
53 lines
1.8 KiB
C#
53 lines
1.8 KiB
C#
namespace ClaudeDo.Ui.Services;
|
|
|
|
// Two named types because DI resolves them by type, not by key.
|
|
public sealed class InstallerLocator() : InstallArtifactLocator("uninstaller", "ClaudeDo.Installer.exe");
|
|
|
|
public sealed class WorkerLocator() : InstallArtifactLocator("worker", "ClaudeDo.Worker.exe");
|
|
|
|
/// <summary>
|
|
/// Locates an executable inside a ClaudeDo install: walk up from the running
|
|
/// directory to the folder containing install.json, otherwise read the
|
|
/// uninstall registry key (which is what makes this work from a dev build).
|
|
/// </summary>
|
|
public abstract class InstallArtifactLocator(string subdir, string exeName)
|
|
{
|
|
private const string InstallJson = "install.json";
|
|
|
|
public string? Find()
|
|
=> FindByWalkingUp(AppContext.BaseDirectory)
|
|
?? (OperatingSystem.IsWindows() ? FindByRegistry() : null);
|
|
|
|
public string? FindByWalkingUp(string startDir)
|
|
{
|
|
var dir = new DirectoryInfo(startDir);
|
|
while (dir is not null)
|
|
{
|
|
if (File.Exists(Path.Combine(dir.FullName, InstallJson)))
|
|
return Candidate(dir.FullName);
|
|
dir = dir.Parent;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
[System.Runtime.Versioning.SupportedOSPlatform("windows")]
|
|
public string? FindByRegistry()
|
|
{
|
|
if (!OperatingSystem.IsWindows()) return null;
|
|
try
|
|
{
|
|
using var key = Microsoft.Win32.Registry.LocalMachine
|
|
.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Uninstall\ClaudeDo");
|
|
var location = key?.GetValue("InstallLocation") as string;
|
|
return string.IsNullOrEmpty(location) ? null : Candidate(location);
|
|
}
|
|
catch { return null; }
|
|
}
|
|
|
|
private string? Candidate(string installDir)
|
|
{
|
|
var path = Path.Combine(installDir, subdir, exeName);
|
|
return File.Exists(path) ? path : null;
|
|
}
|
|
}
|