Make Add-Type usable in application that hosts PowerShell (#10587)

This commit is contained in:
Dongbo Wang 2019-09-25 16:26:19 -07:00 committed by Aditya Patwardhan
parent 985c9d3634
commit 74517923cf
3 changed files with 62 additions and 3 deletions

View file

@ -596,10 +596,24 @@ namespace Microsoft.PowerShell.Commands
#region LoadAssembly
// We now ship .Net Core's reference assemblies with PowerShell, so that Add-Type can work
// We now ship .NET Core's reference assemblies with PowerShell, so that Add-Type can work
// in a predictable way and won't be broken when we move to newer version of .NET Core.
// The reference assemblies are located at '$PSHOME\ref'.
private static readonly string s_netcoreAppRefFolder = PathType.Combine(PathType.GetDirectoryName(typeof(PSObject).Assembly.Location), "ref");
// The reference assemblies are located at '$PSHOME\ref' for pwsh.
//
// For applications that host PowerShell, the 'ref' folder will be deployed to the 'publish'
// folder, not where 'System.Management.Automation.dll' is located. So here we should use
// the entry assembly's location to construct the path to the 'ref' folder.
// For pwsh, the entry assembly is 'pwsh.dll', so the entry assembly's location is still
// $PSHOME.
// However, 'Assembly.GetEntryAssembly()' returns null when the managed code is called from
// unmanaged code (PowerShell WSMan remoting scenario), so in that case, we continue to use
// the location of 'System.Management.Automation.dll'.
private static readonly string s_netcoreAppRefFolder = PathType.Combine(
PathType.GetDirectoryName(
(Assembly.GetEntryAssembly() ?? typeof(PSObject).Assembly).Location),
"ref");
// Path to the folder where .NET Core runtime assemblies are located.
private static readonly string s_frameworkFolder = PathType.GetDirectoryName(typeof(object).Assembly.Location);
// These assemblies are always automatically added to ReferencedAssemblies.

View file

@ -139,5 +139,40 @@ namespace PowerShell.Hosting.SDK.Tests
File.Delete(target);
}
}
/// <summary>
/// Reference assemblies should be handled correctly so that Add-Type works in the hosting scenario.
/// </summary>
[Fact]
public static void TestAddTypeCmdletInHostScenario()
{
string code = @"
using System;
public class Foo
{
public Foo(string name, string path)
{
this.Name = name;
this.Path = path;
}
public string Name;
public string Path;
}
";
using (System.Management.Automation.PowerShell ps = System.Management.Automation.PowerShell.Create())
{
ps.AddCommand("Add-Type").AddParameter("TypeDefinition", code).Invoke();
ps.Commands.Clear();
var results = ps.AddScript("[Foo]::new('Joe', 'Unknown')").Invoke();
Assert.Single(results);
dynamic foo = results[0];
Assert.Equal("Joe", foo.Name);
Assert.Equal("Unknown", foo.Path);
}
}
}
}

View file

@ -1561,6 +1561,16 @@ function New-ILNugetPackage
CreateNugetPlatformFolder -Platform 'unix' -PackageRuntimesFolder $packageRuntimesFolderPath -PlatformBinPath $LinuxFxdBinPath
}
if ($file -eq "Microsoft.PowerShell.SDK.dll")
{
# Copy the '$PSHome\ref' folder to the NuGet package, so 'dotnet publish' can deploy the 'ref' folder to the publish folder.
# This is to make 'Add-Type' work in application that hosts PowerShell.
$contentFolder = New-Item (Join-Path $filePackageFolder "contentFiles\any\any") -ItemType Directory -Force
$dotnetRefAsmFolder = Join-Path -Path $WinFxdBinPath -ChildPath "ref"
Copy-Item -Path $dotnetRefAsmFolder -Destination $contentFolder -Recurse -Force
}
#region nuspec
# filed a tracking bug for automating generation of dependecy list: https://github.com/PowerShell/PowerShell/issues/6247
$deps = [System.Collections.ArrayList]::new()