diff --git a/src/System.Management.Automation/utils/ClrFacade.cs b/src/System.Management.Automation/utils/ClrFacade.cs index cabac1bd335..3ffa6f59bb4 100644 --- a/src/System.Management.Automation/utils/ClrFacade.cs +++ b/src/System.Management.Automation/utils/ClrFacade.cs @@ -54,13 +54,15 @@ internal static IEnumerable GetAssemblies(string namespaceQualifiedTyp } /// - /// Return assemblies from the default load context and the 'individual' load contexts. - /// The 'individual' load contexts are the ones holding assemblies loaded via 'Assembly.Load(byte[])' and 'Assembly.LoadFile'. - /// Assemblies loaded in any custom load contexts are not consider visible to PowerShell to avoid type identity issues. + /// Return the assemblies from the default load context and the assemblies loaded from byte streams through the 'Assembly.Load(byte[])' API. + /// Assemblies that were loaded by 'Assembly.LoadFile' or loaded in any custom load contexts are not consider visible to PowerShell to avoid + /// the type identity issues. We do not discover assemblies loaded by 'Assembly.LoadFile', because this API is usually used by modules built + /// against 'netstandard2.0' or 'net462' to address assembly loading conflicts when working in the PowerShell Core environment. /// private static IEnumerable GetPSVisibleAssemblies() { - const string IndividualAssemblyLoadContext = "System.Runtime.Loader.IndividualAssemblyLoadContext"; + const string LoadContextFullTypeName = "System.Runtime.Loader.IndividualAssemblyLoadContext"; + const string ByteStreamLoadContextName = "Assembly.Load(byte[], ...)"; foreach (Assembly assembly in AssemblyLoadContext.Default.Assemblies) { @@ -72,7 +74,8 @@ private static IEnumerable GetPSVisibleAssemblies() foreach (AssemblyLoadContext context in AssemblyLoadContext.All) { - if (IndividualAssemblyLoadContext.Equals(context.GetType().FullName, StringComparison.Ordinal)) + if (LoadContextFullTypeName.Equals(context.GetType().FullName, StringComparison.Ordinal) + && ByteStreamLoadContextName.Equals(context.Name, StringComparison.Ordinal)) { foreach (Assembly assembly in context.Assemblies) { diff --git a/test/powershell/engine/Basic/Assembly.LoadBytesAndLoadFile.Tests.ps1 b/test/powershell/engine/Basic/Assembly.LoadBytesAndLoadFile.Tests.ps1 index 981a00627e4..e925e28b921 100644 --- a/test/powershell/engine/Basic/Assembly.LoadBytesAndLoadFile.Tests.ps1 +++ b/test/powershell/engine/Basic/Assembly.LoadBytesAndLoadFile.Tests.ps1 @@ -1,7 +1,7 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT License. -Describe "Assembly loaded in IndividualAssemblyLoadContext should be visible to PowerShell" -Tags "CI" { +Describe "Discoverability of assemblies loaded by 'Assembly.Load(byte[])' and 'Assembly.LoadFile'" -Tags "CI" { BeforeAll { $code1 = @' namespace LoadBytes { @@ -39,9 +39,13 @@ Describe "Assembly loaded in IndividualAssemblyLoadContext should be visible to [LoadBytes.MyLoadBytesTest]::GetName() | Should -BeExactly "MyLoadBytesTest" } - It "Assembly loaded via 'Assembly.LoadFile' should be discoverable" { - [System.Reflection.Assembly]::LoadFile($loadFileFile) > $null + It "Assembly loaded via 'Assembly.LoadFile' should NOT be discoverable" { + ## Reflection should work fine. + $asm = [System.Reflection.Assembly]::LoadFile($loadFileFile) + $type = $asm.GetType('LoadFile.MyLoadFileTest') + $type::GetName() | Should -BeExactly "MyLoadFileTest" - [LoadFile.MyLoadFileTest]::GetName() | Should -BeExactly "MyLoadFileTest" + ## Type resolution should not work. + { [LoadFile.MyLoadFileTest] } | Should -Throw -ErrorId "TypeNotFound" } }