1

How can parse the output of powerShell console in C#?

PowerShell console output:

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

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

In my C# code read the output line by line. I search the best way to convert the output to the

List<Dictionary<string, string>> 

I tried

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>();
        }
    }
}
6
  • You might want to show the command you're using to generate that output. Commented Jul 29, 2015 at 16:36
  • Why do you want a list of dictionaries, when it would be sufficient to just have a dictionary of strings? Commented Jul 29, 2015 at 16:36
  • How can i use a dictionary of strings in my case? PS: I added the code that i use. Commented Jul 29, 2015 at 16:52
  • What is the problem you've observed with the approach you're taking? In what way does it not work? Commented Jul 29, 2015 at 17:12
  • It working but I search the optimal way to do this task. Commented Jul 30, 2015 at 7:35

3 Answers 3

2

If the process finishes quickly and doesn't provide a lot of output, then it might be a good idea to wait for it to exit, and then read all of the standard output stream at once.

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()));
}

You'll probably also want to wrap it in try...catch in case the process output is not in the format you expect.

Sign up to request clarification or add additional context in comments.

2 Comments

I don't need a loop to adding the dictionary in list? I receive the error: An Item with the same key has already been added.
I edited my answer, it should now work for you, and output List<Dictionary<string, string>> with each VM being a separate Dictionary<string,string>. It is kind of ugly solution though - I recommend taking the path @n0rd suggested, and get Powershell output as an object if you can.
2

Come on! C# and Powershell - both .Net languages. You can invoke Powershell scripts form C# and get output as objects. No need to parse anything:

    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);
        }
    }

1 Comment

I can not do this. I forgot to say that run on server 2008 PowerShell v2.0. I don't have system.management.automation. I using this library : pshyperv.codeplex.com
0
  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

}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.