From 2f59c7645f85c27e9181fed567fe895d3a824dd6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 19 May 2026 13:00:13 +0000 Subject: [PATCH 1/2] Initial plan From 27fedde7129d69caedf249a725d122e362f7312b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 19 May 2026 13:08:23 +0000 Subject: [PATCH 2/2] Tighten NodeLaunchData.EnvironmentOverrides nullability to IDictionary? Agent-Logs-Url: https://github.com/dotnet/msbuild/sessions/2e8dcdf9-a529-41ff-87b3-72b3b671a758 Co-authored-by: OvesN <150850103+OvesN@users.noreply.github.com> --- src/Build/BackEnd/Client/MSBuildClient.cs | 3 +-- .../Components/Communications/DetouredNodeLauncher.cs | 4 +++- .../BackEnd/Components/Communications/INodeLauncher.cs | 2 +- src/Build/BackEnd/Components/Communications/NodeLauncher.cs | 4 +++- .../Communications/NodeProviderOutOfProcTaskHost.cs | 2 +- src/Framework/DotnetHostEnvironmentHelper.cs | 6 +++--- 6 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/Build/BackEnd/Client/MSBuildClient.cs b/src/Build/BackEnd/Client/MSBuildClient.cs index 4c6a61fb362..fb07bbf31f2 100644 --- a/src/Build/BackEnd/Client/MSBuildClient.cs +++ b/src/Build/BackEnd/Client/MSBuildClient.cs @@ -469,11 +469,10 @@ private bool TryLaunchServer() // Set DOTNET_ROOT so the apphost server child can locate the runtime; this // override is replaced by the client's environment on the first build command // (see OutOfProcServerNode.HandleServerNodeBuildCommand → SetEnvironment). - // The `!` works around dotnet/msbuild#13761. NodeLaunchData launchData = new( MSBuildLocation: _msbuildLocation, CommandLineArgs: string.Join(" ", msBuildServerOptions), - EnvironmentOverrides: DotnetHostEnvironmentHelper.CreateDotnetRootEnvironmentOverrides()!); + EnvironmentOverrides: DotnetHostEnvironmentHelper.CreateDotnetRootEnvironmentOverrides()); using Process msbuildProcess = nodeLauncher.Start(launchData, nodeId: 0); _launchedServerPid = msbuildProcess.Id; diff --git a/src/Build/BackEnd/Components/Communications/DetouredNodeLauncher.cs b/src/Build/BackEnd/Components/Communications/DetouredNodeLauncher.cs index 39dc59dd970..a6e97f9770a 100644 --- a/src/Build/BackEnd/Components/Communications/DetouredNodeLauncher.cs +++ b/src/Build/BackEnd/Components/Communications/DetouredNodeLauncher.cs @@ -144,7 +144,9 @@ public Process Start(NodeLaunchData launchData, int nodeId) /// /// Creates environment variables with optional overrides for app host bootstrap. /// - private static BuildParameters.IBuildParameters CreateEnvironmentVariables(IDictionary environmentOverrides) +#nullable enable annotations + private static BuildParameters.IBuildParameters CreateEnvironmentVariables(IDictionary environmentOverrides) +#nullable disable annotations { var envVars = new Dictionary(); foreach (DictionaryEntry baseVar in Environment.GetEnvironmentVariables()) diff --git a/src/Build/BackEnd/Components/Communications/INodeLauncher.cs b/src/Build/BackEnd/Components/Communications/INodeLauncher.cs index 74fe28309fc..d7b572d3aed 100644 --- a/src/Build/BackEnd/Components/Communications/INodeLauncher.cs +++ b/src/Build/BackEnd/Components/Communications/INodeLauncher.cs @@ -25,7 +25,7 @@ internal readonly record struct NodeLaunchData( string MSBuildLocation, string CommandLineArgs, Handshake? Handshake = null, - IDictionary? EnvironmentOverrides = null); + IDictionary? EnvironmentOverrides = null); internal interface INodeLauncher { diff --git a/src/Build/BackEnd/Components/Communications/NodeLauncher.cs b/src/Build/BackEnd/Components/Communications/NodeLauncher.cs index 923b2e302c8..ae4e7f0c073 100644 --- a/src/Build/BackEnd/Components/Communications/NodeLauncher.cs +++ b/src/Build/BackEnd/Components/Communications/NodeLauncher.cs @@ -287,7 +287,9 @@ private static STARTUPINFOW CreateStartupInfo(bool redirectStreams) /// (caller passes the inherited environment). /// [SupportedOSPlatform("windows")] - private static bool BuildEnvironmentBlock(ref ValueStringBuilder builder, IDictionary environmentOverrides) +#nullable enable annotations + private static bool BuildEnvironmentBlock(ref ValueStringBuilder builder, IDictionary environmentOverrides) +#nullable disable annotations { if (environmentOverrides == null || environmentOverrides.Count == 0) { diff --git a/src/Build/BackEnd/Components/Communications/NodeProviderOutOfProcTaskHost.cs b/src/Build/BackEnd/Components/Communications/NodeProviderOutOfProcTaskHost.cs index c597b77bc61..6afbfd07397 100644 --- a/src/Build/BackEnd/Components/Communications/NodeProviderOutOfProcTaskHost.cs +++ b/src/Build/BackEnd/Components/Communications/NodeProviderOutOfProcTaskHost.cs @@ -817,7 +817,7 @@ private NodeLaunchData ResolveAppHostOrFallback( { CommunicationsUtilities.Trace($"For a host context of {hostContext}, using app host from {appHostPath}."); - IDictionary dotnetOverrides = DotnetHostEnvironmentHelper.CreateDotnetRootEnvironmentOverrides(dotnetHostPath); + var dotnetOverrides = DotnetHostEnvironmentHelper.CreateDotnetRootEnvironmentOverrides(dotnetHostPath); return dotnetOverrides == null ? throw new NodeFailedToLaunchException(errorCode: null, ResourceUtilities.GetResourceString("DotnetHostPathNotSet")) diff --git a/src/Framework/DotnetHostEnvironmentHelper.cs b/src/Framework/DotnetHostEnvironmentHelper.cs index 7ecd6e91bab..09381ab0d28 100644 --- a/src/Framework/DotnetHostEnvironmentHelper.cs +++ b/src/Framework/DotnetHostEnvironmentHelper.cs @@ -99,7 +99,7 @@ internal static void ClearBootstrapDotnetRootEnvironment(IDictionary /// The environment dictionary to modify. /// The overrides to apply. If null, no changes are made. - internal static void ApplyEnvironmentOverrides(IDictionary environment, IDictionary? overrides) + internal static void ApplyEnvironmentOverrides(IDictionary environment, IDictionary? overrides) { if (overrides is null) { return; } - foreach (KeyValuePair kvp in overrides) + foreach (KeyValuePair kvp in overrides) { if (kvp.Value is null) {