【问题标题】:Using a powershell object in C# to retrieve cmdlet get-physicaldisk在 C# 中使用 powershell 对象检索 cmdlet get-physicaldisk
【发布时间】:2021-11-02 04:45:33
【问题描述】:

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”时,没有返回数据,也没有引发错误。


我也尝试过使用Runspace和管道来执行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();

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

我正在使用 System Management 5.0、..Automation 7.1.4 和 Powershell SDK 7.1.4。

【问题讨论】:

    标签: c# powershell runspace


    【解决方案1】:

    Daniel's helpful answer 为手头的案例提供了有效的解决方案。

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

    • .AddScript() PowerShell SDK 方法用于传递另外一个 PowerShell 语句 以执行;也就是说,您可以传递 PowerShell 源代码 的 sn-p,就像在 .ps1 脚​​本 文件 中找到的那样。

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

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

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

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

    相比之下:

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

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

    另见:

    【讨论】:

      【解决方案2】:

      将您的执行策略设置为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();
          }
      }
      

      【讨论】:

      • 干得好;我试图笼统地解释如何诊断问题,但我没有想到模块无法导入的具体原因。
      • 顺便说一句,您知道该模块内部需要使脚本运行吗(顺便说一句:Microsoft.PowerShell.ExecutionPolicy.RemoteSigned 应该足够并且可能更可取)?在原始的 PowerShell 会话中,即使使用策略 Restricted,它也适用于我,但结合在我的 $PROFILE 文件中加载 unrelated 格式数据时,我确实看到了症状。
      • @mklement0,不幸的是我没有。我只是碰巧注意到模块未加载的错误。我已经用RemoteSigned 进行了测试,它也适用于我,所以我更新了我的答案。我无法让它与 Restricted 一起使用
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-19
      • 1970-01-01
      • 2013-03-01
      • 2013-01-06
      • 2018-12-07
      • 1970-01-01
      相关资源
      最近更新 更多