从 .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, Dictionary
2& cmdlets, Dictionary
2& 别名,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, Dictionary
2& cmdlet,Dictionary2& aliases, Dictionary
2& 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, PSDataCollection
1 输出,PSInvocationSettings 设置)在 System.Management.Automation.PowerShell.CoreInvoke[TInput,TOutput](PSDataCollection1 input, PSDataCollection
1 输出,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-x86
和win-x64
。
【讨论】:
谢谢,就是这样!所以这意味着从 .Net Core 运行 Powershell 还不是真正可移植的...... win10-x64 以 Windows Server 2016 为目标 如果您选择其中的“最小公分母”,即win7-x64
或win7-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 查询?