Skip to content

Do not share assemblies of task dependencies if not running on MSBuild.exe.#13285

Open
teo-tsirpanis wants to merge 3 commits intodotnet:mainfrom
teo-tsirpanis:task-dep-alc
Open

Do not share assemblies of task dependencies if not running on MSBuild.exe.#13285
teo-tsirpanis wants to merge 3 commits intodotnet:mainfrom
teo-tsirpanis:task-dep-alc

Conversation

@teo-tsirpanis
Copy link
Copy Markdown
Contributor

@teo-tsirpanis teo-tsirpanis commented Feb 24, 2026

Fixes microsoft/MSBuildLocator#336
Fixes #13286

Context

When MSBuild resolves dependencies for a task, if it cannot find the dependent assembly in the task assembly's directory, it tries finding it in MSBuild's tools directory. In that case, the dependency is loaded to AssemblyLoadContext.Default instead of the task's own ALC, in order to share it across tasks and avoid loading it multiple times.

However, loading it to the default ALC does not reliably work if MSBuild is running on an arbitrary host app (such as by being loaded by MSBuildLocator), because it will cause failures if the host app has itself a dependency on an older assembly version than the task's dependency. This is what caused the linked issue.

Changes Made

Updated MSBuildLoadContext.Load to load dependencies found in the tools directory, into itself, instead of in AssemblyLoadContext.Default. To avoid regressing performance in the majority of cases, the existing behavior is maintained if MSBuild is running as part of MSBuild.exe (detected by checking the entry assembly's name, once in static initialization).

Testing

Validated that the test failures in the linked issue no longer reproduce. I did this by using a custom copy of .NET SDK 8.0.418, with a patched Microsoft.Build.dll.

Notes

Copilot AI review requested due to automatic review settings February 24, 2026 00:52
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes an issue where MSBuild, when loaded via MSBuildLocator into a host application, could fail if the host app had dependencies on older assembly versions than those required by MSBuild tasks. The fix changes how assemblies found in the MSBuild tools directory are loaded into AssemblyLoadContexts (ALCs).

Changes:

  • Modified MSBuildLoadContext.Load to conditionally load dependencies found in the tools directory into either the default ALC (when running as MSBuild.exe) or the plugin's isolated ALC (when running in a host app via MSBuildLocator)
  • Added detection logic to determine if MSBuild is running as MSBuild.exe by checking the entry assembly name

Comment thread src/Shared/MSBuildLoadContext.cs Outdated
Comment thread src/Shared/MSBuildLoadContext.cs Outdated
Copy link
Copy Markdown
Member

@AR-May AR-May left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall looks good to me. I ran experimental insertion with these changes, for a bit of extra test coverage. Let's see whether the tests would pass.

Comment thread src/Shared/MSBuildLoadContext.cs Outdated
@AR-May
Copy link
Copy Markdown
Member

AR-May commented Feb 26, 2026

/azp run

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 1 pipeline(s).

rainersigwald
rainersigwald previously approved these changes Feb 26, 2026
Copy link
Copy Markdown
Member

@AR-May AR-May left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While looking at the additional tests I ran, we realized that the code in this version is not quite correct. MSBuildLoadContext is available and used only in .NET Core version of the MSBuild. Because of that, we should not distinguish between msbuild.exe and an app using MSBuildLocator, since msbuild.exe does not go through this code path at all. Instead, we need to distinguish between dotnet build/run and an app that uses MSBuildLocator and load differently in those cases.

Today, RunningInMSBuildExe is false when running dotnet build, which means this code always loads into a custom ALC. This can potentially cause a performance regression.

@rainersigwald
Copy link
Copy Markdown
Member

Today, RunningInMSBuildExe is false when running dotnet build, which means this code always loads into a custom ALC. This can potentially cause a performance regression.

I talked to @AR-May about this offline, and I'm not sure this is the right behavior. I think this PR may be exactly correct and our definition for RunningInMSBuildExe may be wrong--because I think conceptually what that is supposed to mean is something more like "we fully understand and control the runtime environment" and builds launched through dotnet build and the nodes they launch should count in that category.

We're going to dig into that angle a bit more.

@rainersigwald rainersigwald dismissed their stale review February 26, 2026 15:38

Convinced that this isn't fully right given today's RunningInMSBuildExe.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

6 participants