从 .Net Core 运行 Powershell - 无法加载文件或程序集 Microsoft.Management.Infrastructure

Posted

技术标签:

【中文标题】从 .Net Core 运行 Powershell - 无法加载文件或程序集 Microsoft.Management.Infrastructure【英文标题】:Running Powershell from .Net Core - Could not load file or assembly Microsoft.Management.Infrastructure 【发布时间】:2019-10-14 14:23:55 【问题描述】:

我一直在尝试使用以下代码从 .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,版本=1.0.0.0, 文化=中性,PublicKeyToken=31bf3856ad364e35'。系统无法 找到指定的文件。文件名: 'Microsoft.Management.Infrastructure,版本=1.0.0.0, 文化=中性,PublicKeyToken=31bf3856ad364e35' 在 System.Reflection.RuntimeAssembly.GetExportedTypes(RuntimeAssembly 程序集,ObjectHandleOnStack retTypes)在 System.Reflection.RuntimeAssembly.GetExportedTypes() 在 System.Management.Automation.Runspaces.PSSnapInHelpers.GetAssemblyTypes(装配 程序集,字符串名称)在 System.Management.Automation.Runspaces.PSSnapInHelpers.AnalyzeModuleAssemblyWithReflection(程序集 程序集、字符串名称、PSSnapInInfo psSnapInInfo、PSModuleInfo moduleInfo, Boolean isModuleLoad, Dictionary2& cmdlets, Dictionary2& 别名,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& cmdlet,Dictionary2& aliases, Dictionary2& providers,String& helpFile)在 System.Management.Automation.Runspaces.InitialSessionState.ImportPSSnapIn(PSSnapInInfo psSnapInInfo、PSSnapInException 和警告)在 System.Management.Automation.Runspaces.InitialSessionState.CreateDefault() 在 System.Management.Automation.Runspaces.RunspaceFactory.CreateRunspace(PSHost 主机)在 System.Management.Automation.Runspaces.RunspaceFactory.CreateRunspace() 在 System.Management.Automation.PowerShell.Worker.CreateRunspaceIfNeededAndDoWork(运行空间 rsToUse,布尔 isSync)在 System.Management.Automation.PowerShell.CoreInvokeHelper[TInput,TOutput](PSDataCollection1 input, PSDataCollection1 输出,PSInvocationSettings 设置)在 System.Management.Automation.PowerShell.CoreInvoke[TInput,TOutput](PSDataCollection1 input, PSDataCollection1 输出,PSInvocationSettings 设置)在 System.Management.Automation.PowerShell.CoreInvoke[TOutput](IEnumerable 输入,PSDataCollection`1 输出,PSInvocationSettings 设置)在 System.Management.Automation.PowerShell.Invoke(IEnumerable 输入, PSInvocationSettings 设置)

我不知道我应该安装哪个框架/包以使其运行。 目标框架是已安装的 .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 启动时,该脚本在 prod 上运行良好。显示的错误是 Web 应用程序尝试运行 PowerShell。

编辑4 应用程序池帐户具有管理员权限,并且与我用于手动运行脚本的帐户相同(不是好的做法,但现在我只是尝试运行此脚本)。

编辑5 我尝试将dll放在服务器上应用程序的文件夹中并重新启动站点+回收应用程序池。我尝试了在开发机器上可以找到的每个版本,但没有任何效果:/

编辑6 将 nuget 包从 6.0.5 更新到最新的 6.2.1 ,同样的问题

【问题讨论】:

查看之前的答案:***.com/a/47777636/303696 不幸的是我的代码是相同的,我有相同的 Nuget 包(但版本 6.0.5 而不是 6.0.0-rc)。实际上我从这个答案中找到了运行 powershell 的代码。 您正在使用string command = @"& """c:\\my Folder\\myScript.ps1"""; 中的逐字标识符。在这种情况下,您不需要转义反斜杠,将代码更改为 string command = @"& ""c:\my Folder\myScript.ps1"" "; 你的开发环境是什么,生产环境是什么? @DhruvMurarka Win 10 Pro for dev 和 Win Server 2016 Standard for prod. 【参考方案1】:

我遇到了同样的问题,Microsoft.Management.Infrastructure.dll(和相关文件)没有发布。 通过在发布配置文件中指定 non-portable RID 解决(*.pubxml不是 *.csproj):

<RuntimeIdentifier>win7-x64</RuntimeIdentifier>

问题可能是由于C:\Users\UserName\.nuget\packages\microsoft.management.infrastructure\1.0.0\runtimes 下只有具有不可移植RID 的文件夹;没有win-x86win-x64

【讨论】:

谢谢,就是这样!所以这意味着从 .Net Core 运行 Powershell 还不是真正可移植的...... win10-x64 以 Windows Server 2016 为目标 如果您选择其中的“最小公分母”,即win7-x64win7-x86,它应该可以在所有受支持的Windows 版本上移植。不确定unix。 RID 目录页面上未提及:docs.microsoft.com/en-us/dotnet/core/rid-catalog【参考方案2】:

检查池中 Web 应用程序的应用程序标识池。 可能是权利问题 使用身份模拟或在管理员帐户上运行。 当您从控制台运行时,您使用您的身份运行当您使用应用程序运行时,它的应用程序身份池

【讨论】:

是的,它是应用程序池的相同管理员帐户,也是我用来运行脚本的帐户:( 所以你说 dotnet app 运行这一行 var results = ps.AddScript(command).Invoke();不起作用,但 PS c:\\my Folder\\myScript.ps1 在 ps 提示符下工作 我以应用程序池身份运行,而我的代码试图杀死一些进程,所以这意味着这些停止进程命令在部署到服务器时会失败,对吧?【参考方案3】:

您可以从 Powershell 加载任何 DLL,因此一个绝对可行的解决方案是将 Microsoft.Management.Infrastructure DLL 作为脚本的一部分加载。但在此之前,让我们验证一下在 dev 和 prod powershell 会话中加载的内容之间的区别。

您可以通过运行[Threading.Thread]::GetDomain().GetAssemblies() 来获取 PowerShell 中当前加载的程序集的列表。在脚本的开头和结尾添加这一行(在最后,因为 PowerShell 会在脚本中首次使用引用的程序集时自动加载引用的程序集)。现在在 dev 和 prod 上运行脚本并比较结果。很有可能,Microsoft.Management.Infrastructure 将在 prod 上丢失。

程序集列表输出显示程序集的位置。从开发列表中,获取Microsoft.Management.Infrastructure DLL 文件。您现在有两个选择:

    将文件放入 prod 机器的 GAC。 PowerShell 现在应该会根据需要自动加载 DLL。 将加载此 DLL 文件作为 PowerShell 脚本的一部分。在脚本开头添加[Reflection.Assembly]::LoadFile($fullPathToDLL)(或使用Microsoft.Management.Infrastructure之前的任何位置)。

【讨论】:

有没有办法在 Visual Studio 中做到这一点? 脚本在 PowerShell 中直接启动时运行良好。 .Net 日志中显示了缺少 dll 的错误,所以我认为 .Net 需要 dll,而不是 PowerShell 我想在 GAC 中添加 Microsoft.Management.Infrastructure dll,但它不像你可以像使用它一样拖放文件,所以不确定我是否可以这样做..跨度> 尝试将 DLL 添加到您的项目文件中。根据我的经验,Visual Studio 会自动在您的项目中添加对 DLL 的引用,否则您可以手动添加 DLL 文件。 @rayray 在 VS 中做哪个部分?整件事?【参考方案4】:

将此添加到您的 csproj 中。

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

【讨论】:

对我不起作用... 我在我的项目中使用它并且它可以工作,

以上是关于从 .Net Core 运行 Powershell - 无法加载文件或程序集 Microsoft.Management.Infrastructure的主要内容,如果未能解决你的问题,请参考以下文章

powershell EF6 .Net Core 2现有数据库

我可以使用 .NET Core 编写 PowerShell 二进制 cmdlet 吗?

powershell 管理.NET Core控制台应用程序的用户秘密

如何从 PowerShell 运行 SQL Server 查询?

powershell 从Tridion Sites Core Service获取所有应用程序ID

尝鲜.net core2.1 ——编写一个global tool