diff --git a/src/Framework/Traits.cs b/src/Framework/Traits.cs index 84fde7c36b5..4dc17f9722d 100644 --- a/src/Framework/Traits.cs +++ b/src/Framework/Traits.cs @@ -402,6 +402,13 @@ public bool? LogPropertiesAndItemsAfterEvaluation /// public readonly bool UseSingleLoadContext = Environment.GetEnvironmentVariable("MSBUILDSINGLELOADCONTEXT") == "1"; + /// + /// Use custom AssemblyLoadContext for loading dependencies found in the MSBuild tools directory. + /// When enabled, assemblies found in the MSBuild tools directory are loaded into the plugin's isolated context + /// instead of the shared default context, preventing potential version conflicts with the host application. + /// + public readonly bool UseCustomLoadContextForDependenciesInToolsDirectory = Environment.GetEnvironmentVariable("MSBUILDUSECUSTOMLOADCONTEXTFORDEPENDENCIESINTOOLSDIRECTORY") == "1"; + /// /// Enables the user of autorun functionality in CMD.exe on Windows which is disabled by default in MSBuild. /// diff --git a/src/Shared/MSBuildLoadContext.cs b/src/Shared/MSBuildLoadContext.cs index 3e797529682..db5417b9d78 100644 --- a/src/Shared/MSBuildLoadContext.cs +++ b/src/Shared/MSBuildLoadContext.cs @@ -94,13 +94,15 @@ 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 the custom load context escape hatch + // is enabled (to isolate MSBuild assemblies from the app's dependencies). var assemblyNameInExecutableDirectory = Path.Combine(BuildEnvironmentHelper.Instance.CurrentMSBuildToolsDirectory, $"{assemblyName.Name}.dll"); if (FileSystems.Default.FileExists(assemblyNameInExecutableDirectory)) { - return AssemblyLoadContext.Default.LoadFromAssemblyPath(assemblyNameInExecutableDirectory); + AssemblyLoadContext targetAlc = Framework.Traits.Instance.EscapeHatches.UseCustomLoadContextForDependenciesInToolsDirectory ? this : AssemblyLoadContext.Default; + return targetAlc.LoadFromAssemblyPath(assemblyNameInExecutableDirectory); } return null;