21

I have been trying to run a powershell script from a .Net Core Web app (not discussing best practices here ;) ) with the following code:

    string command = @"& """c:\\my Folder\\myScript.ps1""";

    using (var ps = PowerShell.Create())
    {
        var results = ps.AddScript(command).Invoke();
    }

It works well on my dev machine, but in production it fails when trying to execute this function:

ps.AddScript(command).Invoke()

I get the following exception:

System.IO.FileNotFoundException: Could not load file or assembly 'Microsoft.Management.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'. The system cannot find the file specified. File name: 'Microsoft.Management.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' at System.Reflection.RuntimeAssembly.GetExportedTypes(RuntimeAssembly assembly, ObjectHandleOnStack retTypes) at System.Reflection.RuntimeAssembly.GetExportedTypes() at System.Management.Automation.Runspaces.PSSnapInHelpers.GetAssemblyTypes(Assembly assembly, String name) at System.Management.Automation.Runspaces.PSSnapInHelpers.AnalyzeModuleAssemblyWithReflection(Assembly assembly, String name, PSSnapInInfo psSnapInInfo, PSModuleInfo moduleInfo, Boolean isModuleLoad, Dictionary2& cmdlets, Dictionary2& aliases, Dictionary2& providers, String helpFile, Type& randomCmdletToCheckLinkDemand, Type& randomProviderToCheckLinkDemand) at System.Management.Automation.Runspaces.PSSnapInHelpers.AnalyzePSSnapInAssembly(Assembly assembly, String name, PSSnapInInfo psSnapInInfo, PSModuleInfo moduleInfo, Boolean isModuleLoad, Dictionary2& cmdlets, Dictionary2& aliases, Dictionary2& providers, String& helpFile) at System.Management.Automation.Runspaces.InitialSessionState.ImportPSSnapIn(PSSnapInInfo psSnapInInfo, PSSnapInException& warning) at System.Management.Automation.Runspaces.InitialSessionState.CreateDefault() at System.Management.Automation.Runspaces.RunspaceFactory.CreateRunspace(PSHost host) at System.Management.Automation.Runspaces.RunspaceFactory.CreateRunspace() at System.Management.Automation.PowerShell.Worker.CreateRunspaceIfNeededAndDoWork(Runspace rsToUse, Boolean isSync) at System.Management.Automation.PowerShell.CoreInvokeHelper[TInput,TOutput](PSDataCollection1 input, PSDataCollection1 output, PSInvocationSettings settings) at System.Management.Automation.PowerShell.CoreInvoke[TInput,TOutput](PSDataCollection1 input, PSDataCollection1 output, PSInvocationSettings settings) at System.Management.Automation.PowerShell.CoreInvoke[TOutput](IEnumerable input, PSDataCollection`1 output, PSInvocationSettings settings) at System.Management.Automation.PowerShell.Invoke(IEnumerable input, PSInvocationSettings settings)

I don't know which framework/package I am suppose to install to make it run. Target Framework is .Net Core 2.1 which is installed, hence the application running fine except line mentionned above.

The deps.json file contains this:

    "Microsoft.Management.Infrastructure/1.0.0": {
        "dependencies": {
          "NETStandard.Library": "2.0.3",
          "System.Runtime.CompilerServices.VisualC": "4.3.0",
          "System.Runtime.Serialization.Xml": "4.3.0",
          "System.Security.SecureString": "4.3.0",
          "System.Threading.ThreadPool": "4.3.0"
        },
        "compile": {
          "ref/netstandard1.6/Microsoft.Management.Infrastructure.Native.dll": {},
          "ref/netstandard1.6/Microsoft.Management.Infrastructure.dll": {}
        }
      }

Nuget Packages installed:

Microsoft.AspNetCore.App (2.1.1)
Microsoft.PowerShell.Commands.Diagnostics (6.0.5)
Microsoft.PowerShell.SDK (6.0.5)
Microsoft.PowerShell.WSMan.Management (6.0.5)

Edit I also added Microsoft.Management.Infrastructure (1.0.0) but it didn't fix the issue

Edit2 Dev is Windows 10 Pro and Prod is Windows Server 2016 Standard

Edit3 The script runs fine on prod when launched through PowerShell directly. The error shown is when the Web app tries to run PowerShell.

Edit4 App pool account has admin rights and is the same account that I used to run the script manually (not good practice but for now I'm just trying to make this run).

Edit5 I tried to put the dll in the folder of the app on the server and restart the site + recycle the application pool. I tried with every version I could find on the dev machine and nothing worked :/

Edit6 Updated nuget packages from 6.0.5 to latest 6.2.1 , same issue

Sylvain Gantois
  • 779
  • 1
  • 12
  • 28
  • 1
    Check out this previous answer: https://stackoverflow.com/a/47777636/303696 – Den May 29 '19 at 06:18
  • unfortunately my code is the same and I have the same Nuget packages (but version 6.0.5 instead of 6.0.0-rc). Actually I found the code to run powershell from this answer. – Sylvain Gantois May 29 '19 at 06:28
  • You're using the verbatim identifier in `string command = @"& """c:\\my Folder\\myScript.ps1""";`. In that case you don't need the escape the backslash, change the code to `string command = @"& ""c:\my Folder\myScript.ps1"" ";` – Moerwald May 29 '19 at 07:24
  • What is your dev environment and what is the production environment? – Dhruv Murarka Jun 01 '19 at 07:48
  • @DhruvMurarka Win 10 Pro for dev and Win Server 2016 Standard for prod. – Sylvain Gantois Jun 01 '19 at 08:47
  • When you are publishing your App, what RID are you using? – Bearcat9425 Jun 06 '19 at 19:56
  • @Bearcat9425 When I publish, options I choose: Target Framework: netcoreapp2.1 , Target Runtime: win-x64 (I can choose only between win-x86, win-x64, win-arm, osx-x64, linux-x64, linux-arm), I am using VS 2019 – Sylvain Gantois Jun 06 '19 at 21:23
  • I cannot choose 'win10-x64' or 'Win7-x64' like some people are mentionning on github https://github.com/PowerShell/PowerShell/issues/8119 I suspect it is because my project is a web app... – Sylvain Gantois Jun 07 '19 at 00:33

6 Answers6

31

I had same issue, Microsoft.Management.Infrastructure.dll (and associated files) did not get published. Solved by specifying a non-portable RID in publish profile (*.pubxml, not the *.csproj):

<RuntimeIdentifier>win7-x64</RuntimeIdentifier>

Problem is probably caused by the fact, that under C:\Users\UserName\.nuget\packages\microsoft.management.infrastructure\1.0.0\runtimes there are only folders with non-portable RIDs; there is no win-x86 and win-x64.

George Chakhidze
  • 1,269
  • 12
  • 15
  • 1
    Thanks, that was it ! So that means running Powershell from .Net Core is not really portable yet.. – Sylvain Gantois Jun 28 '19 at 08:28
  • win10-x64 in my case for Windows Server 2016 as a target – Sylvain Gantois Jun 28 '19 at 08:32
  • If you pick "lowest common denominator" among them, which is `win7-x64` or `win7-x86`, it should be portable on all supported versions of Windows. Not sure about `unix`. It is not mentioned on the RID Catalog page: https://learn.microsoft.com/en-us/dotnet/core/rid-catalog – George Chakhidze Jul 05 '19 at 12:37
2

Check application identity pool for Web app in pool. It may be rights issue Use identity impersonation or run on admin account. when you run from console you run with your identity when you run with app its app identity pool

Jin Thakur
  • 2,711
  • 18
  • 15
  • yeah it's the same admin account for the app pool and the one I used to run the script :( – Sylvain Gantois Jun 05 '19 at 12:22
  • So you are saying dotnet app running this line var results = ps.AddScript(command).Invoke(); does not work but PS c:\\my Folder\\myScript.ps1 works from ps prompt – Jin Thakur Jun 11 '19 at 21:45
  • I run with application pool identity and my code attempts to kill some processes, so this means that those stop-process commands would fail when deployed on the server, right? – Sibi John Oct 07 '19 at 15:36
1

You can load any DLL from Powershell, so one solution that should definitely work is loading the Microsoft.Management.Infrastructure DLL as part of the script. But before doing that, let's verify the difference between what's loaded in dev and prod powershell sessions.

You can get the list of currently loaded assemblies in PowerShell by running [Threading.Thread]::GetDomain().GetAssemblies(). Add this line at the start and end of your script (at the end because PowerShell will auto-load referenced assemblies if it can, when they are first used in the script). Now run the script on dev and prod and compare the results. Chances are, Microsoft.Management.Infrastructure will be missing on prod.

The assemblies list output shows the location of the assemblies. From the dev list, grab the Microsoft.Management.Infrastructure DLL file. You now have two options:

  1. Put the file in the prod machine's GAC. PowerShell should now load the DLL automatically as required.
  2. Make loading this DLL file part of your PowerShell script. Add [Reflection.Assembly]::LoadFile($fullPathToDLL) at the start of your script (or anywhere before you use Microsoft.Management.Infrastructure).
Dhruv Murarka
  • 376
  • 5
  • 12
  • Is there a way to do this in Visual Studio? – rayray Jun 03 '19 at 14:43
  • The script runs fine when launched in PowerShell directly. The error of missing dll is shown in the .Net logs so I think the dll is required by .Net, not by PowerShell – Sylvain Gantois Jun 03 '19 at 22:07
  • I thought of adding Microsoft.Management.Infrastructure dlls in the GAC but its not like you can just drag & drop the file as it used it be so not sure if I can do that.. – Sylvain Gantois Jun 03 '19 at 22:11
  • Try adding the DLL to your project files. In my experience Visual studio adds references to DLLs in your project automatically, otherwise you can add the DLL file manually. – Dhruv Murarka Jun 04 '19 at 12:58
  • @rayray do which part in VS? The whole thing? – Dhruv Murarka Jun 04 '19 at 12:59
  • @DhruvMurarka Yes because in my case my application is based in VS – rayray Jun 04 '19 at 13:49
  • If adding the DLL to your project files doesn't work, I would really recommend making loading the DLL part of the script as described in the answer. It will remove dependence on VS or anything else's behaviour. – Dhruv Murarka Jun 04 '19 at 15:01
  • @rayray this application is also based on VS, it's calling Powershell from a C# VS project. If your scenario is different, can you post a separate question? – Dhruv Murarka Jun 04 '19 at 15:04
  • Loading the dll in PowerShell gave me the same error. The dll is required by .Net to load powershell itself, the script hasn't been called yet. – Sylvain Gantois Jun 05 '19 at 12:53
  • Oh I see. Well the last thing I have is placing the required DLL in your project files. Either VS will auto detect it and add a reference, or add the reference to the DLL manually. If that doesn't work, I give up :P – Dhruv Murarka Jun 05 '19 at 14:17
1

Add this in your csproj.

<PackageReference Include="NETStandard.Library" Version="1.6.1" />
Hugues Gauthier
  • 639
  • 8
  • 18
1

publish using... dotnet publish -o .\publish -r win10-x64

https://github.com/PowerShell/PowerShell/issues/7886

  • When you provide an answer. Please provide a fully answer where the questioner does not need to switch to another side :) – Lars Nielsen Aug 01 '22 at 12:13
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Aug 01 '22 at 12:13
0

My converted project had a top-level package System.Management.Infrastructure which was pulling in a transitive dependency for the missing Microsoft.Management.Infrastructure 1.0.. So, I eliminated that and now the correct transitive package Microsoft.Management.Infrastructure 2.0. package is being pulled in by the PowerShell.* 2.0 packages. Note that you can see this using a nifty new feature of VS2022 (version 17.3.5) where you can hover over the transitive packages to see which top-level packages are pulling them in.

batpox
  • 338
  • 2
  • 8