【问题标题】:Parse PowerShell output in C#在 C# 中解析 PowerShell 输出
【发布时间】:2015-07-29 16:33:48
【问题描述】:

如何在 C# 中解析 powerShell 控制台的输出?

PowerShell 控制台输出:

Name        : 0F06B9DF-9FC5-4AF7-AF92-890AAD415000
ElementName : Virtual Machine 1

Name        : 2B501DD8-46F5-45FE-ACCE-62030720A000
ElementName : Virtual Machine 2

在我的 C# 代码中逐行读取输出。我搜索将输出转换为

的最佳方法
List<Dictionary<string, string>> 

我试过了

bool dataset = false;
Dictionary<string, string> data = new Dictionary<string, string>();
proc.Start();
while (!proc.StandardOutput.EndOfStream)
{
    // The line of Output
    string line = proc.StandardOutput.ReadLine();

    // If line is not empty save data in dictionary
    if(line.Length != 0)
    {
        dataset = true;
        string[] vals = line.Split(':');
        data.Add(vals[0], vals[1]);
    }
    // Else, save dictionary in list and reinit dictionary
    else
    {
        // Next object
        if (dataset)
        { 
            arr.Add(data);
            dataset = false;
            data = new Dictionary<string, string>();
        }
    }
}

【问题讨论】:

  • 您可能希望显示用于生成该输出的命令。
  • 为什么你需要一个字典列表,而只有一个字符串字典就足够了?
  • 在我的情况下如何使用字符串字典? PS:我添加了我使用的代码。
  • 您观察到的问题是什么?在什么情况下它不起作用?
  • 它可以工作,但我正在寻找完成这项任务的最佳方式。

标签: c# parsing powershell output


【解决方案1】:

如果进程很快完成并且没有提供大量输出,那么最好等待它退出,然后一次读取所有标准输出流。

proc.WaitForExit((int)TimeSpan.FromSeconds(10).TotalMilliseconds);

var ret = new List<Dictionary<string, string>>();

// first split on double newline to separate VMs
string[] vms = proc.StandardOutput.ReadToEnd()
    .Split(new[] { string.Format("{0}{0}", Environment.NewLine) }, StringSplitOptions.RemoveEmptyEntries);

foreach (var vm in vms)
{
    // then split on newline, to get each line in separate string
    var lines = vm.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);

    // finally, split each line on ':' to fill in dictionary, then add it to list
    ret.Add(lines.Select(line => line.Split(':')).ToDictionary(a => a[0].Trim(), a => a[1].Trim()));
}

您可能还希望将其包装在 try...catch 中,以防进程输出不是您期望的格式。

【讨论】:

  • 我不需要循环来将字典添加到列表中?我收到错误:已添加具有相同密钥的项目。
  • 我编辑了我的答案,它现在应该对你有用,并输出List&lt;Dictionary&lt;string, string&gt;&gt;,每个虚拟机都是一个单独的Dictionary&lt;string,string&gt;。虽然这是一种丑陋的解决方案 - 我建议采用@n0rd 建议的路径,并尽可能将 Powershell 输出作为对象。
【解决方案2】:

来吧! C# 和 Powershell - 都是 .Net 语言。您可以从 C# 调用 Powershell 脚本并将输出作为对象获取。无需解析任何东西:

    static void Main(string[] args)
    {
        var rsc = RunspaceConfiguration.Create();
        var runSpace = RunspaceFactory.CreateRunspace(rsc);
        runSpace.Open();
        Runspace.DefaultRunspace = runSpace;
        var p = runSpace.CreatePipeline("Get-Process");

        var output = p.Invoke();

        foreach (var o in output)
        {
            Console.WriteLine("{0}", o.Properties["Name"].Value);
        }
    }

【讨论】:

  • 我不能这样做。我忘了说在服务器 2008 PowerShell v2.0 上运行。我没有 system.management.automation。我使用这个库:pshyperv.codeplex.com
【解决方案3】:
  using (PowerShell PowerShellInstance = PowerShell.Create())
              {
                  // this script has a sleep in it to simulate a long running script
                  PowerShellInstance.AddScript("GET-VM");
                  //PowerShellInstance.AddCommand("Out-String");
                  // begin invoke execution on the pipeline

                  foreach (var o in PowerShellInstance.Invoke())
                  {
                      //Console.WriteLine(str);
                    Console.WriteLine("{0}", o.Properties["Name"].Value);
                    Console.WriteLine("{0}", o.Properties["Status"].Value);
                }
                  // do something else until execution has completed.
                  // this could be sleep/wait, or perhaps some other work

}

【讨论】:

    猜你喜欢
    • 2022-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-03
    • 2010-12-15
    • 2022-11-25
    • 1970-01-01
    • 2013-03-11
    相关资源
    最近更新 更多