From af73d8210c0df12245bc0c2ef79a8cacc4b11ff4 Mon Sep 17 00:00:00 2001 From: Theodore Tsirpanis Date: Tue, 24 Feb 2026 02:21:36 +0200 Subject: [PATCH 1/3] Do not share assemblies of task dependencies if not running on `MSBuild.exe`. --- src/Shared/MSBuildLoadContext.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Shared/MSBuildLoadContext.cs b/src/Shared/MSBuildLoadContext.cs index 3e797529682..25ff04c801a 100644 --- a/src/Shared/MSBuildLoadContext.cs +++ b/src/Shared/MSBuildLoadContext.cs @@ -29,6 +29,8 @@ internal class MSBuildLoadContext : AssemblyLoadContext "Microsoft.Build.Utilities.Core", ]; + private static readonly bool IsRunningOnMsBuildExecutable = Assembly.GetEntryAssembly()?.GetName().Name is "MSBuild"; + public MSBuildLoadContext(string assemblyPath) : base($"MSBuild plugin {assemblyPath}") { @@ -100,7 +102,11 @@ public MSBuildLoadContext(string assemblyPath) if (FileSystems.Default.FileExists(assemblyNameInExecutableDirectory)) { - return AssemblyLoadContext.Default.LoadFromAssemblyPath(assemblyNameInExecutableDirectory); + // If we are not running on MSBuild.exe (e.g. on an app using MSBuildLocator), we cannot load + // the assembly in the default ALC, because it might interfere with the app's own dependencies. + // In that case, load it in the plugin's isolated ALC. + AssemblyLoadContext alcToLoadSharedDependency = IsRunningOnMsBuildExecutable ? Default : this; + return alcToLoadSharedDependency.LoadFromAssemblyPath(assemblyNameInExecutableDirectory); } return null; From 0497f541ea3c5912ac2ee6c5c43709f7f5fc54cf Mon Sep 17 00:00:00 2001 From: Theodore Tsirpanis Date: Tue, 24 Feb 2026 03:34:04 +0200 Subject: [PATCH 2/3] Address Copilot feedback. --- src/Shared/MSBuildLoadContext.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/Shared/MSBuildLoadContext.cs b/src/Shared/MSBuildLoadContext.cs index 25ff04c801a..74b75a49c8b 100644 --- a/src/Shared/MSBuildLoadContext.cs +++ b/src/Shared/MSBuildLoadContext.cs @@ -29,8 +29,6 @@ internal class MSBuildLoadContext : AssemblyLoadContext "Microsoft.Build.Utilities.Core", ]; - private static readonly bool IsRunningOnMsBuildExecutable = Assembly.GetEntryAssembly()?.GetName().Name is "MSBuild"; - public MSBuildLoadContext(string assemblyPath) : base($"MSBuild plugin {assemblyPath}") { @@ -105,8 +103,8 @@ public MSBuildLoadContext(string assemblyPath) // If we are not running on MSBuild.exe (e.g. on an app using MSBuildLocator), we cannot load // the assembly in the default ALC, because it might interfere with the app's own dependencies. // In that case, load it in the plugin's isolated ALC. - AssemblyLoadContext alcToLoadSharedDependency = IsRunningOnMsBuildExecutable ? Default : this; - return alcToLoadSharedDependency.LoadFromAssemblyPath(assemblyNameInExecutableDirectory); + AssemblyLoadContext targetAlc = BuildEnvironmentHelper.Instance.RunningInMSBuildExe ? Default : this; + return targetAlc.LoadFromAssemblyPath(assemblyNameInExecutableDirectory); } return null; From 95e56e4f17729f5d279379544c473f6a5e495883 Mon Sep 17 00:00:00 2001 From: Theodore Tsirpanis Date: Wed, 25 Feb 2026 21:51:58 +0200 Subject: [PATCH 3/3] Update comments. --- src/Shared/MSBuildLoadContext.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/Shared/MSBuildLoadContext.cs b/src/Shared/MSBuildLoadContext.cs index 74b75a49c8b..fa2bcce58a2 100644 --- a/src/Shared/MSBuildLoadContext.cs +++ b/src/Shared/MSBuildLoadContext.cs @@ -94,15 +94,13 @@ public MSBuildLoadContext(string assemblyPath) // If the Assembly is provided via a file path, the following rules are used to load the assembly: // - the assembly from the user specified path is loaded, if it exists, into the custom ALC, or // - if the simple name of the assembly exists in the same folder as msbuild.exe, then that assembly gets loaded - // into the default ALC (so it's shared with other uses). + // into the default ALC (so it's shared with other uses), or into the custom ALC if we are not running on + // MSBuild.exe (because it might interfere with the app's own dependencies). var assemblyNameInExecutableDirectory = Path.Combine(BuildEnvironmentHelper.Instance.CurrentMSBuildToolsDirectory, $"{assemblyName.Name}.dll"); if (FileSystems.Default.FileExists(assemblyNameInExecutableDirectory)) { - // If we are not running on MSBuild.exe (e.g. on an app using MSBuildLocator), we cannot load - // the assembly in the default ALC, because it might interfere with the app's own dependencies. - // In that case, load it in the plugin's isolated ALC. AssemblyLoadContext targetAlc = BuildEnvironmentHelper.Instance.RunningInMSBuildExe ? Default : this; return targetAlc.LoadFromAssemblyPath(assemblyNameInExecutableDirectory); }