Discover assemblies loaded by 'Assembly.Load(byte[])' and 'Assembly.LoadFile' (#12203)
* Fix regression: pwsh should discover assemblies loaded by 'Assembly.Load(byte[])' and 'Assembly.LoadFile'
This commit is contained in:
parent
dfe9955346
commit
e741dc58dd
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,5 +1,6 @@
|
|||
bin/
|
||||
obj/
|
||||
.ionide/
|
||||
project.lock.json
|
||||
*-tests.xml
|
||||
/debug/
|
||||
|
|
|
@ -58,9 +58,36 @@ namespace System.Management.Automation
|
|||
/// </param>
|
||||
internal static IEnumerable<Assembly> GetAssemblies(string namespaceQualifiedTypeName = null)
|
||||
{
|
||||
return PSAssemblyLoadContext.GetAssembly(namespaceQualifiedTypeName) ??
|
||||
AssemblyLoadContext.Default.Assemblies.Where(a =>
|
||||
!a.FullName.StartsWith(TypeDefiner.DynamicClassAssemblyFullNamePrefix, StringComparison.Ordinal));
|
||||
return PSAssemblyLoadContext.GetAssembly(namespaceQualifiedTypeName) ?? GetPSVisibleAssemblies();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
private static IEnumerable<Assembly> GetPSVisibleAssemblies()
|
||||
{
|
||||
const string IndividualAssemblyLoadContext = "System.Runtime.Loader.IndividualAssemblyLoadContext";
|
||||
|
||||
foreach (Assembly assembly in AssemblyLoadContext.Default.Assemblies)
|
||||
{
|
||||
if (!assembly.FullName.StartsWith(TypeDefiner.DynamicClassAssemblyFullNamePrefix, StringComparison.Ordinal))
|
||||
{
|
||||
yield return assembly;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (AssemblyLoadContext context in AssemblyLoadContext.All)
|
||||
{
|
||||
if (IndividualAssemblyLoadContext.Equals(context.GetType().FullName, StringComparison.Ordinal))
|
||||
{
|
||||
foreach (Assembly assembly in context.Assemblies)
|
||||
{
|
||||
yield return assembly;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
# Copyright (c) Microsoft Corporation.
|
||||
# Licensed under the MIT License.
|
||||
|
||||
Describe "Assembly loaded in IndividualAssemblyLoadContext should be visible to PowerShell" -Tags "CI" {
|
||||
BeforeAll {
|
||||
$code1 = @'
|
||||
namespace LoadBytes {
|
||||
public class MyLoadBytesTest {
|
||||
public static string GetName() { return "MyLoadBytesTest"; }
|
||||
}
|
||||
}
|
||||
'@
|
||||
$code2 = @'
|
||||
namespace LoadFile {
|
||||
public class MyLoadFileTest {
|
||||
public static string GetName() { return "MyLoadFileTest"; }
|
||||
}
|
||||
}
|
||||
'@
|
||||
|
||||
$tempFolderPath = [System.IO.Path]::Combine([System.IO.Path]::GetTempPath(), "IndividualALCTest")
|
||||
New-Item $tempFolderPath -ItemType Directory -Force > $null
|
||||
$loadBytesFile = [System.IO.Path]::Combine($tempFolderPath, "MyLoadBytesTest.dll")
|
||||
$loadFileFile = [System.IO.Path]::Combine($tempFolderPath, "MyLoadFileTest.dll")
|
||||
|
||||
if (-not (Test-Path $loadBytesFile)) {
|
||||
Add-Type -TypeDefinition $code1 -OutputAssembly $loadBytesFile
|
||||
}
|
||||
|
||||
if (-not (Test-Path $loadFileFile)) {
|
||||
Add-Type -TypeDefinition $code2 -OutputAssembly $loadFileFile
|
||||
}
|
||||
}
|
||||
|
||||
It "Assembly loaded via 'Assembly.Load(byte[])' should be discoverable" {
|
||||
$bytes = [System.IO.File]::ReadAllBytes($loadBytesFile)
|
||||
[System.Reflection.Assembly]::Load($bytes) > $null
|
||||
|
||||
[LoadBytes.MyLoadBytesTest]::GetName() | Should -BeExactly "MyLoadBytesTest"
|
||||
}
|
||||
|
||||
It "Assembly loaded via 'Assembly.LoadFile' should be discoverable" {
|
||||
[System.Reflection.Assembly]::LoadFile($loadFileFile) > $null
|
||||
|
||||
[LoadFile.MyLoadFileTest]::GetName() | Should -BeExactly "MyLoadFileTest"
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue