Skip to content
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
531d264
add apphost support
YuliiaKovalova Feb 2, 2026
2e623d0
add e2e tests
YuliiaKovalova Feb 2, 2026
072cb7b
fix the tests
YuliiaKovalova Feb 2, 2026
d023200
avoid target framework hardcoding in codebase
YuliiaKovalova Feb 2, 2026
96159c0
exclude adding source build
YuliiaKovalova Feb 2, 2026
d2d33a6
fix the test
YuliiaKovalova Feb 3, 2026
95f4da2
revert the condition
YuliiaKovalova Feb 3, 2026
68880eb
fix the tests
YuliiaKovalova Feb 3, 2026
ad34e84
Merge branch 'main' into dev/ykovalova/app_host_support
YuliiaKovalova Feb 4, 2026
16ac07f
Merge remote-tracking branch 'origin/main' into dev/ykovalova/app_hos…
YuliiaKovalova Feb 4, 2026
5b0b950
Merge branch 'dev/ykovalova/app_host_support' of https://github.com/d…
YuliiaKovalova Feb 4, 2026
0fd74ed
fix review commet
YuliiaKovalova Feb 4, 2026
1e5e8c3
fix the issue
YuliiaKovalova Feb 4, 2026
fc15e94
undo changes in tests
YuliiaKovalova Feb 4, 2026
d2004c9
undo more change
YuliiaKovalova Feb 4, 2026
0d3288f
fix the tests
YuliiaKovalova Feb 4, 2026
011735e
more test fixes
YuliiaKovalova Feb 4, 2026
4daad92
more test fixes
YuliiaKovalova Feb 4, 2026
fb8eb1e
fix a typo
YuliiaKovalova Feb 4, 2026
72bbf09
Update cibuild_bootstrapped_msbuild.ps1
YuliiaKovalova Feb 4, 2026
e9a28f6
update build env helper
YuliiaKovalova Feb 5, 2026
e517aa0
Merge branch 'dev/ykovalova/app_host_support' of https://github.com/d…
YuliiaKovalova Feb 5, 2026
6aaadfb
various fixes around tests + use app host on repo build
YuliiaKovalova Feb 6, 2026
4812435
return smaller timeout
YuliiaKovalova Feb 6, 2026
cfeb1f5
fix some of review comments
YuliiaKovalova Feb 9, 2026
db70e68
refactor nodelauncher
YuliiaKovalova Feb 9, 2026
7612dea
merge
YuliiaKovalova Feb 9, 2026
60c2d79
fix the tests
YuliiaKovalova Feb 9, 2026
cbe4fff
fix the tests and avoid hardcoded app name
YuliiaKovalova Feb 10, 2026
b9d8d49
more changes around tests and logic
YuliiaKovalova Feb 11, 2026
07e999a
merge
YuliiaKovalova Feb 11, 2026
0d7153f
fix the last tests in BuildManager
YuliiaKovalova Feb 11, 2026
7433663
fix the comments
YuliiaKovalova Feb 12, 2026
ffbbf48
merge
YuliiaKovalova Feb 12, 2026
8b1070e
fix review comment
YuliiaKovalova Feb 13, 2026
c992bc9
fix nullability
YuliiaKovalova Feb 13, 2026
6f7ce52
try to revert condition
YuliiaKovalova Feb 13, 2026
34b7f33
undo extra changes in tests (?)
YuliiaKovalova Feb 13, 2026
6c71b1b
fix review comments
YuliiaKovalova Feb 16, 2026
0c89f3c
Merge remote-tracking branch 'origin/main' into dev/ykovalova/app_hos…
YuliiaKovalova Feb 16, 2026
afe69cb
Remove .dll.config/.exe.config special case
rainersigwald Feb 18, 2026
4c78263
Simplify XSD logic
rainersigwald Feb 18, 2026
053267f
nit: fix indentation
rainersigwald Feb 18, 2026
7ac345b
SupportedOSPlatform in NodeLauncher
rainersigwald Feb 18, 2026
e7e6e2d
include output
rainersigwald Feb 18, 2026
a7d3b23
Keep looking for MSBuild.dll.config on core
rainersigwald Feb 18, 2026
86063a3
Simplify NetTaskHostTest_AppHostUsedWhenAvailable
rainersigwald Feb 18, 2026
5d9d7a9
Be explicit about config file name
rainersigwald Feb 18, 2026
2f8faad
fix the failing test
YuliiaKovalova Feb 19, 2026
0c305bd
add .ToLowerInvariant()
YuliiaKovalova Feb 19, 2026
bf5f9d7
merge + fix for Unix build
YuliiaKovalova Feb 25, 2026
ef893fe
merge
YuliiaKovalova Feb 25, 2026
7cbb0f2
merge
YuliiaKovalova Feb 26, 2026
0dae95d
fixx null ref
YuliiaKovalova Feb 26, 2026
3811ee8
Merge remote-tracking branch 'upstream/main' into dev/ykovalova/app_h…
rainersigwald Feb 27, 2026
2c19de4
fix the failure
YuliiaKovalova Mar 2, 2026
442f453
Merge branch 'main' into dev/ykovalova/app_host_support
YuliiaKovalova Mar 2, 2026
b459f9c
remove extra property
YuliiaKovalova Mar 2, 2026
1726a4e
Merge branch 'dev/ykovalova/app_host_support' of https://github.com/d…
YuliiaKovalova Mar 2, 2026
f9e027c
Merge branch 'main' into dev/ykovalova/app_host_support
baronfel Mar 2, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@ The code is written in C# and should follow the .NET coding conventions. Use the
You should generally match the style of surrounding code when making edits, but if making a substantial change, you can modernize more aggressively.
New files should use nullable types but don't refactor aggressively existing code.

### Nullable Reference Types
- **New files**: Always use nullable reference types (do NOT add `#nullable disable`)
- **Existing files with `#nullable disable`**: Match the existing style; don't add nullable annotations (`?`) to types
- **Existing files with nullable enabled**: Use proper nullable annotations
- When a file has `#nullable disable`, parameters like `IDictionary<string, string>` should NOT have `?` suffix
- Shared files (in `src/Shared/`) may be compiled into multiple assemblies with different nullable contexts; be careful with nullable annotations in these files

Generate tests for new codepaths, and add tests for any bugs you fix. Use the existing test framework, which is xUnit with Shouldly assertions. Use Shouldly assertions for all assertions in modified code, even if the file is predominantly using xUnit assertions.

When making changes, check if related documentation exists in the `documentation/` folder (including `documentation/specs/`) and update it to reflect your changes. Keep documentation in sync with code changes, especially for telemetry, APIs, and architectural decisions.
Expand Down
159 changes: 159 additions & 0 deletions src/Build.UnitTests/BackEnd/AppHostSupport_Tests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Collections.Generic;
using System.IO;
using Microsoft.Build.BackEnd;
using Microsoft.Build.Internal;
using Microsoft.Build.Shared;
using Microsoft.Build.UnitTests;
using Shouldly;
using Xunit;
using Xunit.Abstractions;

#nullable disable

namespace Microsoft.Build.Engine.UnitTests.BackEnd
{
/// <summary>
/// Tests for MSBuild App Host support functionality.
/// Tests the DOTNET_ROOT environment variable handling for app host bootstrap.
/// </summary>
public sealed class AppHostSupport_Tests
{
private readonly ITestOutputHelper _output;

private readonly string _dotnetHostPath = NativeMethodsShared.IsWindows
? @"C:\Program Files\dotnet\dotnet.exe"
: "/usr/share/dotnet/dotnet";

public AppHostSupport_Tests(ITestOutputHelper output)
{
_output = output;
}

[Fact]
public void CreateDotnetRootEnvironmentOverrides_SetsDotnetRootFromHostPath()
{
var overrides = DotnetHostEnvironmentHelper.CreateDotnetRootEnvironmentOverrides(_dotnetHostPath);

overrides.ShouldNotBeNull();
overrides.ShouldContainKey("DOTNET_ROOT");

string expectedDotnetRoot = Path.GetDirectoryName(_dotnetHostPath);
overrides["DOTNET_ROOT"].ShouldBe(expectedDotnetRoot);
}

[Fact]
public void CreateDotnetRootEnvironmentOverrides_ClearsArchitectureSpecificVariables()
{
var overrides = DotnetHostEnvironmentHelper.CreateDotnetRootEnvironmentOverrides(_dotnetHostPath);

// Assert - architecture-specific variables should be set to null (to be cleared)
overrides.ShouldContainKey("DOTNET_ROOT_X64");
overrides["DOTNET_ROOT_X64"].ShouldBeNull();

overrides.ShouldContainKey("DOTNET_ROOT_X86");
overrides["DOTNET_ROOT_X86"].ShouldBeNull();

overrides.ShouldContainKey("DOTNET_ROOT_ARM64");
overrides["DOTNET_ROOT_ARM64"].ShouldBeNull();
}


[WindowsOnlyTheory]
[InlineData(@"C:\custom\sdk\dotnet.exe", @"C:\custom\sdk")]
[InlineData(@"D:\tools\dotnet\dotnet.exe", @"D:\tools\dotnet")]
public void CreateDotnetRootEnvironmentOverrides_HandlesVariousPaths_Windows(string hostPath, string expectedRoot)
{
var overrides = DotnetHostEnvironmentHelper.CreateDotnetRootEnvironmentOverrides(hostPath);

overrides["DOTNET_ROOT"].ShouldBe(expectedRoot);
}

[UnixOnlyTheory]
[InlineData("/usr/local/share/dotnet/dotnet", "/usr/local/share/dotnet")]
[InlineData("/home/user/.dotnet/dotnet", "/home/user/.dotnet")]
public void CreateDotnetRootEnvironmentOverrides_HandlesVariousPaths_Unix(string hostPath, string expectedRoot)
{
var overrides = DotnetHostEnvironmentHelper.CreateDotnetRootEnvironmentOverrides(hostPath);

overrides["DOTNET_ROOT"].ShouldBe(expectedRoot);
}

[Fact]
public void ClearBootstrapDotnetRootEnvironment_ClearsVariablesNotInOriginalEnvironment()
{
using (TestEnvironment env = TestEnvironment.Create(_output))
{
// Arrange - set DOTNET_ROOT variants that simulate app host bootstrap
env.SetEnvironmentVariable("DOTNET_ROOT", @"C:\TestDotnet");
env.SetEnvironmentVariable("DOTNET_ROOT_X64", @"C:\TestDotnetX64");

// Original environment does NOT have these variables
var originalEnvironment = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);

DotnetHostEnvironmentHelper.ClearBootstrapDotnetRootEnvironment(originalEnvironment);

Environment.GetEnvironmentVariable("DOTNET_ROOT").ShouldBeNull();
Environment.GetEnvironmentVariable("DOTNET_ROOT_X64").ShouldBeNull();
}
}

[Fact]
public void ClearBootstrapDotnetRootEnvironment_PreservesVariablesInOriginalEnvironment()
{
using (TestEnvironment env = TestEnvironment.Create(_output))
{
// Arrange - set DOTNET_ROOT that was in the original environment
string originalValue = @"C:\OriginalDotnet";
env.SetEnvironmentVariable("DOTNET_ROOT", originalValue);

// Register other DOTNET_ROOT variants with TestEnvironment so cleanup works correctly.
// These will be cleared by the helper if not in originalEnvironment.
env.SetEnvironmentVariable("DOTNET_ROOT_X64", null);
env.SetEnvironmentVariable("DOTNET_ROOT_X86", null);
env.SetEnvironmentVariable("DOTNET_ROOT_ARM64", null);

// Original environment HAS DOTNET_ROOT
var originalEnvironment = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
{
["DOTNET_ROOT"] = originalValue
};

DotnetHostEnvironmentHelper.ClearBootstrapDotnetRootEnvironment(originalEnvironment);

// Assert - DOTNET_ROOT should be preserved since it was in original environment
Environment.GetEnvironmentVariable("DOTNET_ROOT").ShouldBe(originalValue);
}
}

[Fact]
public void ClearBootstrapDotnetRootEnvironment_HandlesMixedScenario()
{
using (TestEnvironment env = TestEnvironment.Create(_output))
{
string originalDotnetRoot = @"C:\OriginalDotnet";
string bootstrapX64 = @"C:\BootstrapX64";

env.SetEnvironmentVariable("DOTNET_ROOT", originalDotnetRoot);
env.SetEnvironmentVariable("DOTNET_ROOT_X64", bootstrapX64);
env.SetEnvironmentVariable("DOTNET_ROOT_X86", @"C:\BootstrapX86");

// Original environment has DOTNET_ROOT but not the architecture-specific ones
var originalEnvironment = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
{
["DOTNET_ROOT"] = originalDotnetRoot
};

DotnetHostEnvironmentHelper.ClearBootstrapDotnetRootEnvironment(originalEnvironment);

Environment.GetEnvironmentVariable("DOTNET_ROOT").ShouldBe(originalDotnetRoot); // Preserved
Environment.GetEnvironmentVariable("DOTNET_ROOT_X64").ShouldBeNull(); // Cleared
Environment.GetEnvironmentVariable("DOTNET_ROOT_X86").ShouldBeNull(); // Cleared
Environment.GetEnvironmentVariable("DOTNET_ROOT_ARM64").ShouldBeNull(); // Was already null
}
}
}
}
81 changes: 68 additions & 13 deletions src/Build.UnitTests/NetTaskHost_E2E_Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@ namespace Microsoft.Build.Engine.UnitTests
{
public class NetTaskHost_E2E_Tests
{
private const string LatestDotNetCoreForMSBuild = "net10.0";

private static string AssemblyLocation { get; } = Path.Combine(Path.GetDirectoryName(typeof(NetTaskHost_E2E_Tests).Assembly.Location) ?? AppContext.BaseDirectory);

private static string TestAssetsRootPath { get; } = Path.Combine(AssemblyLocation, "TestAssets");
Expand All @@ -29,8 +27,10 @@ public NetTaskHost_E2E_Tests(ITestOutputHelper output)
}

[WindowsFullFrameworkOnlyFact]
public void NetTaskHostTest()
public void NetTaskHostTest_FallbackToDotnet()
{
// This test verifies the fallback behavior when app host is not used.
// When DOTNET_HOST_PATH points to system dotnet, it uses dotnet.exe + MSBuild.dll.
Comment thread
YuliiaKovalova marked this conversation as resolved.
using TestEnvironment env = TestEnvironment.Create(_output);
var dotnetPath = env.GetEnvironmentVariable("DOTNET_ROOT");

Expand All @@ -47,7 +47,7 @@ public void NetTaskHostTest()
testTaskOutput.ShouldContain($"The task is executed in process: dotnet");
testTaskOutput.ShouldContain($"Process path: {dotnetPath}", customMessage: testTaskOutput);

var customTaskAssemblyLocation = Path.GetFullPath(Path.Combine(AssemblyLocation, "..", LatestDotNetCoreForMSBuild, "ExampleTask.dll"));
var customTaskAssemblyLocation = Path.GetFullPath(Path.Combine(AssemblyLocation, "..", RunnerUtilities.LatestDotNetCoreForMSBuild, "ExampleTask.dll"));
var resource = ResourceUtilities.FormatResourceStringIgnoreCodeAndKeyword(
"TaskAssemblyLocationMismatch",

Expand All @@ -57,6 +57,46 @@ public void NetTaskHostTest()
testTaskOutput.ShouldNotContain(resource);
}

[WindowsFullFrameworkOnlyFact] // Verifies that when MSBuild.exe app host is available in the SDK, it is used instead of dotnet.exe + MSBuild.dll.
public void NetTaskHostTest_AppHostUsedWhenAvailable()
{
using TestEnvironment env = TestEnvironment.Create(_output, setupDotnetEnvVars: true);
string testProjectPath = Path.Combine(TestAssetsRootPath, "ExampleNetTask", "TestNetTask", "TestNetTask.csproj");

string testTaskOutput = RunnerUtilities.ExecBootstrapedMSBuild($"{testProjectPath} -restore -v:n -p:LatestDotNetCoreForMSBuild={RunnerUtilities.LatestDotNetCoreForMSBuild}", out bool successTestTask);

successTestTask.ShouldBeTrue();

// When app host is used, the process name should be "MSBuild" not "dotnet"
testTaskOutput.ShouldContain("The task is executed in process: MSBuild");

// The process path should point to MSBuild.exe, not dotnet.exe
testTaskOutput.ShouldContain("MSBuild.exe", customMessage: "Expected MSBuild.exe app host to be used");
testTaskOutput.ShouldNotContain("Process path: " + Path.Combine(env.GetEnvironmentVariable("DOTNET_ROOT") ?? "", "dotnet.exe"));
}

[WindowsFullFrameworkOnlyFact] // Verifies that when using the app host, DOTNET_ROOT is properly set for child processes to find the runtime.
public void NetTaskHostTest_AppHostSetsDotnetRoot()
{
using TestEnvironment env = TestEnvironment.Create(_output);

// Clear DOTNET_ROOT to ensure app host sets it
env.SetEnvironmentVariable("DOTNET_ROOT", null);
env.SetEnvironmentVariable("DOTNET_ROOT_X64", null);
env.SetEnvironmentVariable("DOTNET_ROOT_X86", null);
env.SetEnvironmentVariable("DOTNET_ROOT_ARM64", null);

string testProjectPath = Path.Combine(TestAssetsRootPath, "ExampleNetTask", "TestNetTask", "TestNetTask.csproj");

string testTaskOutput = RunnerUtilities.ExecBootstrapedMSBuild($"{testProjectPath} -restore -v:n -p:LatestDotNetCoreForMSBuild={RunnerUtilities.LatestDotNetCoreForMSBuild}", out bool successTestTask);

_output.WriteLine(testTaskOutput);

// The build should succeed - this proves DOTNET_ROOT was properly set for the task host
// to find the runtime, even though we cleared it from the parent environment
successTestTask.ShouldBeTrue(customMessage: "Build should succeed with app host setting DOTNET_ROOT");
}

[WindowsFullFrameworkOnlyFact]
public void NetTaskHost_CorrectPathsEscapingTest()
{
Expand All @@ -75,8 +115,8 @@ public void NetTaskHost_CorrectPathsEscapingTest()

// Explicitly validate escaping for paths with spaces
var msBuildDllPathMatch = System.Text.RegularExpressions.Regex.Match(
testTaskOutput,
@"Arg\[0\]:\s*(.+)",
testTaskOutput,
@"Arg\[0\]:\s*(.+)",
System.Text.RegularExpressions.RegexOptions.CultureInvariant);

msBuildDllPathMatch.Success.ShouldBeTrue();
Expand All @@ -90,10 +130,10 @@ public void NetTaskHost_CorrectPathsEscapingTest()
{
// Check that later path segments don't appear as separate command line arguments
var arg1Match = System.Text.RegularExpressions.Regex.Match(
testTaskOutput,
@"Arg\[1\]:\s*(.+)",
testTaskOutput,
@"Arg\[1\]:\s*(.+)",
System.Text.RegularExpressions.RegexOptions.CultureInvariant);

if (arg1Match.Success)
{
string arg1Value = arg1Match.Groups[1].Value.Trim();
Expand All @@ -108,7 +148,7 @@ public void NetTaskHost_CorrectPathsEscapingTest()
testTaskOutput,
@"Command line:\s*(.+)",
System.Text.RegularExpressions.RegexOptions.CultureInvariant);

if (cmdLineMatch.Success)
{
string cmdLine = cmdLineMatch.Groups[1].Value.Trim();
Expand All @@ -123,7 +163,6 @@ public void MSBuildTaskInNetHostTest()
using TestEnvironment env = TestEnvironment.Create(_output);

string testProjectPath = Path.Combine(TestAssetsRootPath, "ExampleNetTask", "TestMSBuildTaskInNet", "TestMSBuildTaskInNet.csproj");

string testTaskOutput = RunnerUtilities.ExecBootstrapedMSBuild($"{testProjectPath} -restore -v:n -p:LatestDotNetCoreForMSBuild={RunnerUtilities.LatestDotNetCoreForMSBuild}", out bool successTestTask);

if (!successTestTask)
Expand All @@ -135,8 +174,8 @@ public void MSBuildTaskInNetHostTest()
testTaskOutput.ShouldContain($"Hello TEST");
}

[WindowsFullFrameworkOnlyFact]
public void NetTaskWithImplicitHostParamsTest()
[WindowsFullFrameworkOnlyFact] // This test verifies the fallback behavior with implicit host parameters.
public void NetTaskWithImplicitHostParamsTest_FallbackToDotnet()
{
using TestEnvironment env = TestEnvironment.Create(_output);
var dotnetPath = env.GetEnvironmentVariable("DOTNET_ROOT");
Expand All @@ -163,5 +202,21 @@ public void NetTaskWithImplicitHostParamsTest()
// Output from the task where neither TaskHost nor Runtime were specified
testTaskOutput.ShouldContain("Found item: Banana");
}

[WindowsFullFrameworkOnlyFact] // This test verifies app host behavior with implicit host parameters.
public void NetTaskWithImplicitHostParamsTest_AppHost()
{
using TestEnvironment env = TestEnvironment.Create(_output, setupDotnetEnvVars: true);
string testProjectPath = Path.Combine(TestAssetsRootPath, "ExampleNetTask", "TestNetTaskWithImplicitParams", "TestNetTaskWithImplicitParams.csproj");

string testTaskOutput = RunnerUtilities.ExecBootstrapedMSBuild($"{testProjectPath} -restore -v:n -p:LatestDotNetCoreForMSBuild={RunnerUtilities.LatestDotNetCoreForMSBuild}", out bool successTestTask);

_output.WriteLine(testTaskOutput);

successTestTask.ShouldBeTrue();

testTaskOutput.ShouldContain("The task is executed in process: MSBuild");
testTaskOutput.ShouldContain("/nodereuse:True");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@ internal sealed class DetouredNodeLauncher : INodeLauncher, IBuildComponent
{
private readonly List<ISandboxedProcess> _sandboxedProcesses = new();

private readonly BuildParameters.IBuildParameters _environmentVariables = CreateEnvironmentVariables();

private IFileAccessManager _fileAccessManager;

public static IBuildComponent CreateComponent(BuildComponentType type)
Expand All @@ -51,9 +49,9 @@ public void ShutdownComponent()
}

/// <summary>
/// Creates a new MSBuild process
/// Creates a new MSBuild process.
/// </summary>
public Process Start(string msbuildLocation, string commandLineArgs, int nodeId)
public Process Start(string msbuildLocation, string commandLineArgs, int nodeId, IDictionary<string, string> environmentOverrides = null)
{
// Should always have been set already.
ErrorUtilities.VerifyThrowInternalLength(msbuildLocation, nameof(msbuildLocation));
Expand Down Expand Up @@ -92,7 +90,7 @@ public Process Start(string msbuildLocation, string commandLineArgs, int nodeId)
PipDescription = "MSBuild",
PipSemiStableHash = 0,
Arguments = commandLineArgs,
EnvironmentVariables = _environmentVariables,
EnvironmentVariables = CreateEnvironmentVariables(environmentOverrides),
MaxLengthInMemory = 0, // Don't buffer any output
};

Expand Down Expand Up @@ -140,14 +138,26 @@ public Process Start(string msbuildLocation, string commandLineArgs, int nodeId)
return Process.GetProcessById(sp.ProcessId);
}

private static BuildParameters.IBuildParameters CreateEnvironmentVariables()
/// <summary>
/// Creates environment variables with optional overrides for app host bootstrap.
/// </summary>
/// <param name="environmentOverrides">
/// Environment variables to set or remove in the child process.
/// A non-null value sets or overrides that variable. A null value removes the variable
/// from the child process environment - this is used to clear architecture-specific
/// DOTNET_ROOT variants (e.g., DOTNET_ROOT_X64) that would otherwise take precedence
/// over DOTNET_ROOT when launching an app host.
/// </param>
private static BuildParameters.IBuildParameters CreateEnvironmentVariables(IDictionary<string, string> environmentOverrides)
{
var envVars = new Dictionary<string, string>();
foreach (DictionaryEntry baseVar in Environment.GetEnvironmentVariables())
{
envVars.Add((string)baseVar.Key, (string)baseVar.Value);
}

DotnetHostEnvironmentHelper.ApplyEnvironmentOverrides(envVars, environmentOverrides);

return BuildParameters.GetFactory().PopulateFromDictionary(envVars);
}

Expand Down
Loading
Loading