From 55c84693108a2252bdcb17df3399c1985c580fe1 Mon Sep 17 00:00:00 2001 From: Jayanthi Date: Thu, 22 Oct 2026 14:28:22 -0700 Subject: [PATCH 1/6] override to Let ServiceControl tools roll forward to the latest installed .NET patch --- src/Particular.PlatformSample/AppLauncher.cs | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/Particular.PlatformSample/AppLauncher.cs b/src/Particular.PlatformSample/AppLauncher.cs index 8d96453..5b25353 100644 --- a/src/Particular.PlatformSample/AppLauncher.cs +++ b/src/Particular.PlatformSample/AppLauncher.cs @@ -16,6 +16,13 @@ sealed class AppLauncher(bool showPlatformToolConsoleOutput) : IAsyncDisposable readonly bool hideConsoleOutput = !showPlatformToolConsoleOutput; readonly Stack> cleanupActions = new(); + // ServiceControl is built to require one exact .NET runtime patch version. Let the ServiceControl tools + // use the latest installed patch of the same major.minor version instead, if that exact version is not installed. + static readonly Dictionary serviceControlEnvironmentVariables = new() + { + { "DOTNET_ROLL_FORWARD", "LatestPatch" } + }; + public async Task RavenDB(string logsPath, string dataDirectory, CancellationToken cancellationToken = default) { var licenseFilePath = Path.Combine(platformPath, "servicecontrol", "servicecontrol-instance", "Persisters", "RavenDB", "RavenLicense.json"); @@ -101,7 +108,7 @@ public void ServiceControl(int port, int maintenancePort, string logPath, string return ValueTask.CompletedTask; }); - StartProcess(Path.Combine(platformPath, "servicecontrol", "servicecontrol-instance", "ServiceControl.dll")); + StartProcess(Path.Combine(platformPath, "servicecontrol", "servicecontrol-instance", "ServiceControl.dll"), serviceControlEnvironmentVariables); } public void ServiceControlAudit(int port, int maintenancePort, string logPath, string transportPath, Uri connectionString) @@ -123,7 +130,7 @@ public void ServiceControlAudit(int port, int maintenancePort, string logPath, s return ValueTask.CompletedTask; }); - StartProcess(Path.Combine(platformPath, "servicecontrol", "servicecontrol-audit-instance", "ServiceControl.Audit.dll")); + StartProcess(Path.Combine(platformPath, "servicecontrol", "servicecontrol-audit-instance", "ServiceControl.Audit.dll"), serviceControlEnvironmentVariables); } public void Monitoring(int port, string logPath, string transportPath) @@ -143,7 +150,7 @@ public void Monitoring(int port, string logPath, string transportPath) return ValueTask.CompletedTask; }); - StartProcess(Path.Combine(platformPath, "servicecontrol", "monitoring-instance", "ServiceControl.Monitoring.dll")); + StartProcess(Path.Combine(platformPath, "servicecontrol", "monitoring-instance", "ServiceControl.Monitoring.dll"), serviceControlEnvironmentVariables); } public void ServicePulse(int port, int serviceControlPort, int monitoringPort, string defaultRoute) @@ -179,7 +186,7 @@ void StartProcess(string assemblyPath, Dictionary environmentVar { foreach (var item in environmentVariables) { - startInfo.EnvironmentVariables.Add(item.Key, item.Value); + startInfo.Environment[item.Key] = item.Value; } } From 428fa663f9004eb2c357124c3134db4eb8c6dab9 Mon Sep 17 00:00:00 2001 From: Jayanthi Date: Thu, 22 Oct 2026 14:40:15 -0700 Subject: [PATCH 2/6] update comment --- src/Particular.PlatformSample/AppLauncher.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Particular.PlatformSample/AppLauncher.cs b/src/Particular.PlatformSample/AppLauncher.cs index 5b25353..f6fdc31 100644 --- a/src/Particular.PlatformSample/AppLauncher.cs +++ b/src/Particular.PlatformSample/AppLauncher.cs @@ -16,8 +16,8 @@ sealed class AppLauncher(bool showPlatformToolConsoleOutput) : IAsyncDisposable readonly bool hideConsoleOutput = !showPlatformToolConsoleOutput; readonly Stack> cleanupActions = new(); - // ServiceControl is built to require one exact .NET runtime patch version. Let the ServiceControl tools - // use the latest installed patch of the same major.minor version instead, if that exact version is not installed. + // ServiceControl is built to require one exact .NET runtime patch version. Let the ServiceControl tools run on + // the latest installed patch of the same major.minor version instead, so they still start when that exact version is not installed. static readonly Dictionary serviceControlEnvironmentVariables = new() { { "DOTNET_ROLL_FORWARD", "LatestPatch" } From 664d1d7a0438298c4fc9816d9c2c9ca3396f7614 Mon Sep 17 00:00:00 2001 From: Jayanthi Date: Thu, 22 Oct 2026 17:25:51 -0700 Subject: [PATCH 3/6] Update src/Particular.PlatformSample/AppLauncher.cs Co-authored-by: Michelle Chamberlin --- src/Particular.PlatformSample/AppLauncher.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Particular.PlatformSample/AppLauncher.cs b/src/Particular.PlatformSample/AppLauncher.cs index f6fdc31..bcac51d 100644 --- a/src/Particular.PlatformSample/AppLauncher.cs +++ b/src/Particular.PlatformSample/AppLauncher.cs @@ -16,7 +16,7 @@ sealed class AppLauncher(bool showPlatformToolConsoleOutput) : IAsyncDisposable readonly bool hideConsoleOutput = !showPlatformToolConsoleOutput; readonly Stack> cleanupActions = new(); - // ServiceControl is built to require one exact .NET runtime patch version. Let the ServiceControl tools run on + // ServiceControl is built to require one exact .NET runtime patch version. Since this is for running samples and not production code, we can let the ServiceControl tools run on // the latest installed patch of the same major.minor version instead, so they still start when that exact version is not installed. static readonly Dictionary serviceControlEnvironmentVariables = new() { From 610cc08432ec16a2a8fe3d370a255701ae12cc1a Mon Sep 17 00:00:00 2001 From: Jayanthi Date: Thu, 22 Oct 2026 17:54:59 -0700 Subject: [PATCH 4/6] Pass --roll-forward LatestPatch to dotnet instead of setting DOTNET_ROLL_FORWARD --- src/Particular.PlatformSample/AppLauncher.cs | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/Particular.PlatformSample/AppLauncher.cs b/src/Particular.PlatformSample/AppLauncher.cs index bcac51d..9af8cd0 100644 --- a/src/Particular.PlatformSample/AppLauncher.cs +++ b/src/Particular.PlatformSample/AppLauncher.cs @@ -16,13 +16,6 @@ sealed class AppLauncher(bool showPlatformToolConsoleOutput) : IAsyncDisposable readonly bool hideConsoleOutput = !showPlatformToolConsoleOutput; readonly Stack> cleanupActions = new(); - // ServiceControl is built to require one exact .NET runtime patch version. Since this is for running samples and not production code, we can let the ServiceControl tools run on - // the latest installed patch of the same major.minor version instead, so they still start when that exact version is not installed. - static readonly Dictionary serviceControlEnvironmentVariables = new() - { - { "DOTNET_ROLL_FORWARD", "LatestPatch" } - }; - public async Task RavenDB(string logsPath, string dataDirectory, CancellationToken cancellationToken = default) { var licenseFilePath = Path.Combine(platformPath, "servicecontrol", "servicecontrol-instance", "Persisters", "RavenDB", "RavenLicense.json"); @@ -108,7 +101,7 @@ public void ServiceControl(int port, int maintenancePort, string logPath, string return ValueTask.CompletedTask; }); - StartProcess(Path.Combine(platformPath, "servicecontrol", "servicecontrol-instance", "ServiceControl.dll"), serviceControlEnvironmentVariables); + StartProcess(Path.Combine(platformPath, "servicecontrol", "servicecontrol-instance", "ServiceControl.dll")); } public void ServiceControlAudit(int port, int maintenancePort, string logPath, string transportPath, Uri connectionString) @@ -130,7 +123,7 @@ public void ServiceControlAudit(int port, int maintenancePort, string logPath, s return ValueTask.CompletedTask; }); - StartProcess(Path.Combine(platformPath, "servicecontrol", "servicecontrol-audit-instance", "ServiceControl.Audit.dll"), serviceControlEnvironmentVariables); + StartProcess(Path.Combine(platformPath, "servicecontrol", "servicecontrol-audit-instance", "ServiceControl.Audit.dll")); } public void Monitoring(int port, string logPath, string transportPath) @@ -150,7 +143,7 @@ public void Monitoring(int port, string logPath, string transportPath) return ValueTask.CompletedTask; }); - StartProcess(Path.Combine(platformPath, "servicecontrol", "monitoring-instance", "ServiceControl.Monitoring.dll"), serviceControlEnvironmentVariables); + StartProcess(Path.Combine(platformPath, "servicecontrol", "monitoring-instance", "ServiceControl.Monitoring.dll")); } public void ServicePulse(int port, int serviceControlPort, int monitoringPort, string defaultRoute) @@ -178,6 +171,11 @@ void StartProcess(string assemblyPath, Dictionary environmentVar WorkingDirectory = workingDirectory, UseShellExecute = false }; + // ServiceControl is built to require one exact .NET runtime patch version. Since this is for running samples and not production code, + // let the platform tools run on the latest installed patch of the same major.minor version, so they still start when that exact version + // is not installed. These are options for the dotnet host, so they must come before the assembly path. + startInfo.ArgumentList.Add("--roll-forward"); + startInfo.ArgumentList.Add("LatestPatch"); // Adding the assembly path to the argument list to prevent the path from being separated in to different arguments // by the ProcessStartInfo constructor by spaces. startInfo.ArgumentList.Add(assemblyPath); @@ -186,7 +184,7 @@ void StartProcess(string assemblyPath, Dictionary environmentVar { foreach (var item in environmentVariables) { - startInfo.Environment[item.Key] = item.Value; + startInfo.EnvironmentVariables.Add(item.Key, item.Value); } } From 536e8255c2985c8983578e2114ff648767d02ac8 Mon Sep 17 00:00:00 2001 From: Jayanthi Date: Thu, 22 Oct 2026 17:56:28 -0700 Subject: [PATCH 5/6] Clean up comment in AppLauncher.cs Remove redundant comment about .NET runtime patch version. --- src/Particular.PlatformSample/AppLauncher.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Particular.PlatformSample/AppLauncher.cs b/src/Particular.PlatformSample/AppLauncher.cs index 9af8cd0..edefd37 100644 --- a/src/Particular.PlatformSample/AppLauncher.cs +++ b/src/Particular.PlatformSample/AppLauncher.cs @@ -173,7 +173,7 @@ void StartProcess(string assemblyPath, Dictionary environmentVar }; // ServiceControl is built to require one exact .NET runtime patch version. Since this is for running samples and not production code, // let the platform tools run on the latest installed patch of the same major.minor version, so they still start when that exact version - // is not installed. These are options for the dotnet host, so they must come before the assembly path. + // is not installed. startInfo.ArgumentList.Add("--roll-forward"); startInfo.ArgumentList.Add("LatestPatch"); // Adding the assembly path to the argument list to prevent the path from being separated in to different arguments From 32bbc0a03b4bdf0ce12874c51b47be9b01099b45 Mon Sep 17 00:00:00 2001 From: Jayanthi Date: Fri, 23 Oct 2026 16:15:36 -0700 Subject: [PATCH 6/6] Apply suggestion from @soujay --- src/Particular.PlatformSample/AppLauncher.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Particular.PlatformSample/AppLauncher.cs b/src/Particular.PlatformSample/AppLauncher.cs index edefd37..c7d4251 100644 --- a/src/Particular.PlatformSample/AppLauncher.cs +++ b/src/Particular.PlatformSample/AppLauncher.cs @@ -175,7 +175,7 @@ void StartProcess(string assemblyPath, Dictionary environmentVar // let the platform tools run on the latest installed patch of the same major.minor version, so they still start when that exact version // is not installed. startInfo.ArgumentList.Add("--roll-forward"); - startInfo.ArgumentList.Add("LatestPatch"); + startInfo.ArgumentList.Add("Minor"); // Adding the assembly path to the argument list to prevent the path from being separated in to different arguments // by the ProcessStartInfo constructor by spaces. startInfo.ArgumentList.Add(assemblyPath);