From cdbb4156f8d175d4b94f2e35077d38039665bcc3 Mon Sep 17 00:00:00 2001 From: Simon Cropp Date: Sat, 22 Aug 2026 14:48:42 +1000 Subject: [PATCH] Register the tray's real path at startup Startup.Add guessed %USERPROFILE%\.dotnet\tools\DiffEngineTray.exe. That is only right for a default global install: a --tool-path install, a DOTNET_CLI_HOME that moves the tools directory, or simply running a local build all registered a path with nothing at it. The tray then never started at login, while the Options checkbox - which reads the settings file, not the registry - went on saying it would. Environment.ProcessPath is where this executable actually is. The value is also quoted now, since a Run entry is a command line and an unquoted path containing a space is read as a program name followed by arguments. I also tried pointing the Options checkbox at Startup.Exists, so it reports what the registry says rather than what the settings file wants. That makes the form's rendering depend on the registry of whatever machine runs the tests, and it broke two OptionsForm snapshots here for that reason - so it is not in this commit. With the path itself correct the two agree in the ordinary case, and making a snapshot test read machine state to fix a display nit is a bad trade. --- src/DiffEngineTray/Startup.cs | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/src/DiffEngineTray/Startup.cs b/src/DiffEngineTray/Startup.cs index a752467a..3d84a1cd 100644 --- a/src/DiffEngineTray/Startup.cs +++ b/src/DiffEngineTray/Startup.cs @@ -2,12 +2,32 @@ public class Startup { + /// + /// Registers this executable, wherever it actually is. + /// + /// The path used to be guessed as %USERPROFILE%\.dotnet\tools\DiffEngineTray.exe, which + /// is only right for a default global install. A --tool-path install, a + /// DOTNET_CLI_HOME that moves the tools directory, or simply running a local build all + /// registered a path with nothing at it - so the tray never started at login, while the + /// Options checkbox, which reads the settings file rather than the registry, went on reporting + /// that it would. + /// + /// + /// Quoted, because a Run value is a command line: an unquoted path containing a space is read + /// as a program name followed by arguments. + /// + /// public static void Add() { - var profile = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile); - var exePath = Path.Combine(profile, ".dotnet", "tools", "DiffEngineTray.exe"); + var exePath = Environment.ProcessPath; + if (exePath == null) + { + // No host path to register, which a normal launch does not produce + return; + } + using var key = GetRunKey(); - key.SetValue("DiffEngineTray", exePath); + key.SetValue("DiffEngineTray", $"\"{exePath}\""); } public static void Remove() @@ -25,4 +45,4 @@ public static bool Exists() static RegistryKey GetRunKey() => Registry.CurrentUser .OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Run", true)!; -} \ No newline at end of file +}