Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -596,10 +596,24 @@ protected override void EndProcessing()

#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.
Expand Down
35 changes: 35 additions & 0 deletions test/hosting/test_HostingBasic.cs
Original file line number Diff line number Diff line change
Expand Up @@ -139,5 +139,40 @@ public static void TestCommandFromNative()
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);
}
}
}
}
10 changes: 10 additions & 0 deletions tools/packaging/packaging.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down