Powershell: Import-Module BinaryCmdlet.psd1 doesn't work in .netcoreapp3.1

Created on 3 Mar 2020  路  3Comments  路  Source: PowerShell/PowerShell

When a BinaryCmdlet.psd1 file specifies a RootModule = 'BinaryCmdlet.dll', Import-Module BinaryCmdlet.psd1 fails because the assemblies for Microsoft.PowerShell.SDK nuget package are "reference assemblies" and not copied directly to the publish output. This behavior worked fine for netcoreapp2.1 target framework moniker with Microsoft.PowerShell.SDK 6.2.1.

Note that in other .NET application entry point contexts, such as ASP.NET Core, the <PreserveCompilationContext>true</PreserveCompilationContext> csproj setting can be enabled to copy reference assemblies to publish/refs folder, but then there still needs to be a way to load the reference assemblies. The generated .deps.json file does not seem to be able to instruct the PowerShell executable/.NET Core runtime to load these files. I've searched around for how to resolve this problem, and feel I am very close to finding the solution, but perhaps just missing the "last detail" required to solve the problem.

This issue includes a full, fairly minimal repro below.

Did you do the following?

Steps to reproduce

  1. Clone https://github.com/jzabroski/Microsoft.PowerShell.SDK.Issue
  2. Change Directory (cd) to repository root.
  3. Run dotnet publish .\Microsoft.PowerShell.SDK.Issue\Microsoft.PowerShell.SDK.Issue.sln
  4. Open PwSh.exe and run:
    powershell Import-Module .\Microsoft.PowerShell.SDK.Issue\bin\Debug\netcoreapp3.1\Microsoft.PowerShell.SDK.Issue.psd1
    Note that directly importing the dll-as-a-module also fails:
    powershell Import-Module .\Microsoft.PowerShell.SDK.Issue\bin\Debug\netcoreapp3.1\Microsoft.PowerShell.SDK.Issue.dll

    Expected behavior

I expect the command to succeed and load the module without error.

Actual behavior

Import-Module : Could not load file or assembly 'System.Runtime, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. The system cannot find the file specified.
At line:1 char:1
+ Import-Module D:\source\GitHub\Microsoft.PowerShell.SDK.Issue\Microso ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : NotSpecified: (:) [Import-Module], FileNotFoundException
+ FullyQualifiedErrorId : System.IO.FileNotFoundException,Microsoft.PowerShell.Commands.ImportModuleCommand

Environment data

$PSVersionTable

Name                           Value
----                           -----
PSVersion                      6.2.1
PSEdition                      Core
GitCommitId                    6.2.1
OS                             Microsoft Windows 10.0.17763
Platform                       Win32NT
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0鈥
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0
Issue-Question Resolution-Answered

Most helpful comment

@SeeminglyScience Thank you for your efforts. It worked! You are on the "I owe a beer to this person" list.

All 3 comments

@jzabroski With this change it works:

diff --git a/Microsoft.PowerShell.SDK.Issue/Microsoft.PowerShell.SDK.Issue.csproj b/Microsoft.PowerShell.SDK.Issue/Microsoft.PowerShell.SDK.Issue.csproj
index c2217ce..bdb272e 100644
--- a/Microsoft.PowerShell.SDK.Issue/Microsoft.PowerShell.SDK.Issue.csproj
+++ b/Microsoft.PowerShell.SDK.Issue/Microsoft.PowerShell.SDK.Issue.csproj
@@ -3,8 +3,6 @@
   <PropertyGroup>
     <TargetFramework>netcoreapp3.1</TargetFramework>
     <OutputType>library</OutputType>
-    <PreserveCompilationContext>true</PreserveCompilationContext>
-    <CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
     <GenerateAssemblyInfo>true</GenerateAssemblyInfo>
   </PropertyGroup>

@@ -17,8 +15,8 @@
   </ItemGroup>

   <ItemGroup>
-    <PackageReference Include="Microsoft.Management.Infrastructure" Version="2.0.0" />
-    <PackageReference Include="Microsoft.PowerShell.SDK" Version="6.2.1" />
+    <PackageReference Include="Microsoft.Management.Infrastructure" Version="2.0.0" PrivateAssets="all" />
+    <PackageReference Include="Microsoft.PowerShell.SDK" Version="6.2.1" PrivateAssets="all" />
   </ItemGroup>

-</Project>
\ No newline at end of file
+</Project>

You don't need to actually ship any of that in a PowerShell module because it'll all already be loaded in the AppDomain. If you try to ship your own version then it'll try to load them and fail because a newer version is already present.

Edit: Marking as outdated. It does work in PS7, but so does the original. See comment below.

Are you trying to load a module targeting netcoreapp3.1 in PowerShell 6.2.1? If so, because PowerShell ships with it's own version of the framework, you can't load a newer version. If you want netcoreapp3.1, you need to require PowerShell 7.

@SeeminglyScience Thank you for your efforts. It worked! You are on the "I owe a beer to this person" list.

Was this page helpful?
0 / 5 - 0 ratings