在 C# 中使用 powershell 对象检索 cmdlet get-physicaldisk

Using a powershell object in C# to retrieve cmdlet get-physicaldisk

C#9 中的 Powershell 对象问题

我正在尝试使用 system.management.powershell 对象在 C# 中检索物理磁盘。 当我尝试使用 cmdlet“Get-Process”时,powershell 对象正确检索所有进程。

  using (PowerShell PowerShellInstance = PowerShell.Create())
    {
        // this works
        //PowerShellInstance.AddCommand("Get-Process");
        PowerShellInstance.AddScript("Get-PhysicalDisk");
        //PowerShellInstance.AddCommand("Out-String -Width 240 -Stream");
        Collection<PSObject> outlist = PowerShellInstance.Invoke();
    }

当我尝试使用 cmdlet“Get-PhysicalDevice”时,没有返回任何数据,也没有抛出任何错误。


我也试过使用运行空间和管道执行get-process,所有进程都正确返回。

Runspace rs = RunspaceFactory.CreateRunspace();
rs.Open();
Pipeline p = rs.CreatePipeline();
p.Commands.Add("get-process");
// p.Commands.Add("get-physicaldisk");
Collection<PSObject> results = p.Invoke();
rs.Close();

当我尝试使用运行空间的 get-physicaldisk 时,程序抛出命令未找到异常。 我正在将服务器监视器从 VB 转移到 C#。 Runspace (get-physicaldisk) 在 VB 中使用 .net Framework 4.1.7 正常工作。

我正在使用系统管理 5.0、..Automation 7.1.4 和 Powershell SDK 7.1.4。

为手头的案例提供了有效的解决方案。

此回答解释了PowerShell SDK 如何报告错误以及如何检查它们:

  • .AddScript()PowerShell SDK方法是为了多传递一个PowerShell语句执行;也就是说,您可以传递一段 PowerShell 源代码,就像您在 .ps1 脚本 文件.[=37 中找到的那样=]

  • 相比之下,.AddCommand()方法接受单个PowerShell的名称可执行路径命令 - 没有参数;后者必须通过单独的调用添加,即通过单个 .AddParameters() 调用,或通过参数单独的 .AddParameter().AddArgument() 调用。

选择一种方法而不是另一种方法对错误处理有影响,特别是语句终止错误,例如当调用一个 不存在的命令时 或者,你的情况就是这样,一个模块导入失败的命令:

  • .AddScript() 添加的代码在调用 .Invoke() 不会 抛出 .NET 异常并发生语句终止错误- 相反,返回一个 空集合 .HadErrors 属性 returns true,并且发生的错误可以通过 .Streams.Error 集合进行检查。

  • .AddCommand()- 添加的代码 可能 抛出 .NET 异常,例如类型 System.Management.Automation.CommandNotFoundException.

对比:

  • Script-终止错误(使用 throw 语句或通过 $ErrorActionPreference = 'Stop' / -ErrorAction Stop 创建的错误)总是为调用者创建一个 .NET 异常。

    • throw 作为 PowerShell 语句,只能通过 .AddScript() 执行,但设置 $ErrorActionPreference / 使用 -ErrorAction 也可以与 [=12] 结合使用=].
  • -终止错误(例如,Get-ChildItem nosuchfile从不为以下内容创建 .NET 异常来电者。

另请参阅:

将您的执行策略设置为RemoteSigned以便可以导入存储模块

using (var runspace = RunspaceFactory.CreateRunspace())
{
    runspace.InitialSessionState.ExecutionPolicy = Microsoft.PowerShell.ExecutionPolicy.RemoteSigned;
    runspace.Open();
    using (PowerShell PowerShellInstance = PowerShell.Create(runspace))
    {
        PowerShellInstance.AddScript("Get-PhysicalDisk");
        Collection<PSObject> outlist = PowerShellInstance.Invoke();
    }
}