在.NET Core中运行Powershell-无法加载文件或程序集Microsoft.Management.Infrastructure

21

我一直在尝试使用以下代码从一个.Net Core Web应用程序中运行powershell脚本(不讨论最佳实践 ;)):

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

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

在我的开发机上它运行良好,但在生产环境中尝试执行此函数时会失败:

ps.AddScript(command).Invoke()

我遇到了以下异常:

System.IO.FileNotFoundException:无法加载文件或程序集'Microsoft.Management.Infrastructure,Version=1.0.0.0,Culture=neutral,PublicKeyToken=31bf3856ad364e35'。系统找不到指定的文件。文件名:'Microsoft.Management.Infrastructure,Version=1.0.0.0,Culture=neutral,PublicKeyToken=31bf3856ad364e35' 在 System.Reflection.RuntimeAssembly.GetExportedTypes(RuntimeAssembly assembly, ObjectHandleOnStack retTypes)、System.Reflection.RuntimeAssembly.GetExportedTypes()、System.Management.Automation.Runspaces.PSSnapInHelpers.GetAssemblyTypes(Assembly assembly, String name)、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)、System.Management.Automation.Runspaces.PSSnapInHelpers.AnalyzePSSnapInAssembly(Assembly assembly, String name, PSSnapInInfo psSnapInInfo, PSModuleInfo moduleInfo, Boolean isModuleLoad, Dictionary2& cmdlets, Dictionary2& aliases, Dictionary2& providers, String& helpFile)、System.Management.Automation.Runspaces.InitialSessionState.ImportPSSnapIn(PSSnapInInfo psSnapInInfo, PSSnapInException& warning)、System.Management.Automation.Runspaces.InitialSessionState.CreateDefault()、System.Management.Automation.Runspaces.RunspaceFactory.CreateRunspace(PSHost host)、System.Management.Automation.Runspaces.RunspaceFactory.CreateRunspace()、System.Management.Automation.PowerShell.Worker.CreateRunspaceIfNeededAndDoWork(Runspace rsToUse, Boolean isSync)、System.Management.Automation.PowerShell.CoreInvokeHelper[TInput,TOutput](PSDataCollection1 input, PSDataCollection1 output, PSInvocationSettings settings)、System.Management.Automation.PowerShell.CoreInvoke[TInput,TOutput](PSDataCollection1 input, PSDataCollection1 output, PSInvocationSettings settings)、System.Management.Automation.PowerShell.CoreInvoke[TOutput](IEnumerable input, PSDataCollection`1 output, PSInvocationSettings settings)、System.Management.Automation.PowerShell.Invoke(IEnumerable input, PSInvocationSettings settings)

我不知道我应该安装哪个框架/包才能使其运行。 目标框架是已安装的 .Net Core 2.1,因此应用程序除了上述提到的行之外都运行良好。

deps.json 文件包含以下内容:

    "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包:

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)

编辑 我还添加了Microsoft.Management.Infrastructure (1.0.0),但问题没有得到解决。

编辑2 Dev使用的是Windows 10 Pro,而Prod使用的是Windows Server 2016 Standard。

编辑3 当脚本直接通过PowerShell启动时,在生产环境上运行良好。错误显示在Web应用程序尝试运行PowerShell时出现。

编辑4 应用程序池帐户具有管理员权限,并且是我手动运行脚本时使用的相同帐户(这不是一个好习惯,但现在我只是想让它运行)。

编辑5 我尝试将dll放入服务器上应用程序的文件夹中,并重新启动网站以及回收应用程序池。我尝试使用我在开发机器上能找到的每个版本,但都没有起作用 :/。

编辑6 将nuget包从6.0.5更新到最新的6.2.1,但问题依旧。


1
请查看此前的答案:https://dev59.com/YlkT5IYBdhLWcg3wB7XP#47777636 - Den
不幸的是,我的代码和Nuget包都是相同的(但版本为6.0.5而不是6.0.0-rc)。实际上,我从这个答案中找到了运行PowerShell的代码。 - Sylvain Gantois
你正在使用verbatim标识符在string command = @"& """c:\\my Folder\\myScript.ps1""";。在这种情况下,您不需要转义反斜杠,请将代码更改为string command = @"& ""c:\my Folder\myScript.ps1"" "; - Moerwald
你的开发环境和生产环境分别是什么? - Dhruv Murarka
@Bearcat9425 当我发布时,我选择的选项是:目标框架:netcoreapp2.1,目标运行时:win-x64(我只能在 win-x86、win-x64、win-arm、osx-x64、linux-x64、linux-arm 之间选择),我正在使用 VS 2019。 - Sylvain Gantois
显示剩余3条评论
6个回答

32

我曾经遇到同样的问题,Microsoft.Management.Infrastructure.dll(以及相关文件)未能被发布。通过在发布配置文件(*.pubxml)中指定非便携式RID(而不是*.csproj)解决了这个问题:

<RuntimeIdentifier>win7-x64</RuntimeIdentifier>

问题可能是由于在C:\Users\UserName\.nuget\packages\microsoft.management.infrastructure\1.0.0\runtimes下只有使用非便携RID的文件夹,没有win-x86win-x64


1
谢谢,就是这样!这意味着从 .Net Core 运行 Powershell 还不太可移植。 - Sylvain Gantois
在我的情况下,针对Windows Server 2016,win10-x64是目标。 - Sylvain Gantois
如果你在它们中间选择“最低公共分母”,也就是 win7-x64 或者 win7-x86,那么它应该可以在所有支持的 Windows 版本上运行。不确定是否适用于 unix。RID 目录页面上没有提到:https://learn.microsoft.com/en-us/dotnet/core/rid-catalog - George Chakhidze

2

检查Web应用程序池的应用程序标识池。

可能是权限问题。

使用身份模拟或以管理员帐户运行。

当您在控制台上运行时,您会使用自己的标识运行,而当您使用应用程序运行时,它是应用程序的标识池。

将其视为“最初的回答”。


是的,这个应用程序池的管理员帐户和我用来运行脚本的帐户是相同的 :( - Sylvain Gantois
所以你的意思是,dotnet应用程序运行这一行var results = ps.AddScript(command).Invoke();不起作用,但是从ps提示符中PS c:\my Folder\myScript.ps1可以工作。 - Jin Thakur
我使用应用程序池标识运行,并且我的代码尝试终止一些进程,这意味着当部署到服务器上时,那些停止进程的命令将会失败,对吗? - Sibi John

1

在你的csproj文件中添加以下内容。

<PackageReference Include="NETStandard.Library" Version="1.6.1" />

对我没用... - Rye bread
我在我的项目中使用这个,它能够工作, <PackageReference Include="Microsoft.PowerShell.SDK" Version="6.2.4" /> <PackageReference Include="NETStandard.Library" Version="1.6.1" /> - Hugues Gauthier

1
您可以从PowerShell加载任何DLL,因此应该肯定有效的解决方案之一是将Microsoft.Management.Infrastructure DLL作为脚本的一部分进行加载。但在这样做之前,让我们验证dev和prod powershell会话中加载的内容的差异。
您可以通过运行[Threading.Thread] :: GetDomain()。GetAssemblies()来获取PowerShell中当前加载的程序集列表。在脚本的开头和结尾添加此行代码(在结尾处,因为PowerShell会自动加载引用的程序集,如果可以,在脚本中首次使用它们)。现在在dev和prod上运行脚本并比较结果。很有可能,Microsoft.Management.Infrastructure在prod上丢失。
程序集列表输出显示程序集的位置。从dev列表中获取Microsoft.Management.Infrastructure DLL文件。现在您有两个选项:
1.将文件放入prod机器的GAC中。 PowerShell现在应根据需要自动加载DLL。
2.将加载此DLL文件作为PowerShell脚本的一部分。在脚本的开头添加[Reflection.Assembly] :: LoadFile($fullPathToDLL)(或在使用Microsoft.Management.Infrastructure之前的任何位置)。

在Visual Studio中有没有一种方法可以做到这一点? - rayray
@rayray 在VS中做哪一部分?整个项目吗? - Dhruv Murarka
@DhruvMurarka 是的,因为在我的情况下,我的应用程序是基于VS的。 - rayray
@rayray 这个应用程序也是基于VS的,它从一个C# VS项目中调用Powershell。如果你的情况不同,请另外发一个问题? - Dhruv Murarka
在PowerShell中加载dll给了我相同的错误。该dll是由.Net要求加载powershell本身,脚本尚未被调用。 - Sylvain Gantois
显示剩余5条评论

1

当您提供答案时,请提供完整的答案,使提问者不需要切换到另一个页面 :) - Lars Nielsen
目前你的回答不够清晰,请编辑并添加更多细节,以帮助其他人理解它如何回答问题。你可以在帮助中心找到有关如何编写好答案的更多信息。 - Community

0

我的转换项目有一个顶级包System.Management.Infrastructure,它引入了一个缺失的Microsoft.Management.Infrastructure 1.0的传递依赖项。因此,我消除了它,现在正确的传递包Microsoft.Management.Infrastructure 2.0。包被PowerShell.* 2.0包拉入。请注意,您可以使用VS2022(版本17.3.5)的一个新功能,将鼠标悬停在传递包上,以查看哪些顶级包正在引入它们。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接