3

I'm trying to figure out how to split some cmd output into multiple strings that I can use later to set labels.

The code i'm using is:

ProcessStartInfo diskdrive = new ProcessStartInfo("wmic", " diskdrive get index, model, interfacetype, size");
diskdrive.UseShellExecute = false;
diskdrive.RedirectStandardOutput = true;
diskdrive.CreateNoWindow = true;
var proc = Process.Start(diskdrive);

string s = proc.StandardOutput.ReadToEnd();

It gives an output like this:

Index  InterfaceType  Model                   Size           
2      IDE            WesternDigital    1000202273280  
1      IDE            Seagate             500105249280   
0      IDE            SAMSUNG SSD 830 Series  128034708480

Is it possible to put this in a list or an array so I can get for example the size of disk 2, or the interfacetype of disk 0. I can do some basic things in C# but this is over my head :I

6
  • Di you try with String.Split? Or Regex? Commented Jun 5, 2015 at 14:05
  • String.Split will be problematic if some cells have spaces (as in "SAMSUNG SSD 830 Series". Commented Jun 5, 2015 at 14:06
  • Split string won't do it here, it's because of the spaces I don't know how to tackle this. Commented Jun 5, 2015 at 15:44
  • 4
    Instead of shelling out to an external app to get your WMI information, you can query WMI directly in c#. Then you could access each data field directly without the need for splitting any strings. WMI queries in C# are SQL queries that gather information about the system. For example: var allPDisks = Session.QueryInstances(@"root\microsoft\windows\storage", "WQL", "SELECT * FROM MSFT_PhysicalDisk") The MSFT_PhysicalDisk class provides all of the fields you are trying to get. See this link Commented Jun 5, 2015 at 15:57
  • You need to start with the facts: there will always be 4 columns, the first and last column will always be a numeric; try and work work backwards from that to get the remaining columns parsed and then you can build your list. Commented Jun 8, 2015 at 7:34

2 Answers 2

1

Here is a working example. "result" will contain a list with the relevant parts you require. This is a first pass and i'm sure can be refactored somewhat:

using System;
using System.Collections.Generic;
using System.Linq;

namespace columnmatch
{
    internal class Program
    {

        private const string Ex1 = "2      IDE            WesternDigital    1000202273280";
        private const string Ex2 = "1      IDE            Seagate             500105249280 ";
        private const string Ex3 = "0      IDE            SAMSUNG SSD 830 Series  128034708480";

        private static void Main(string[] args)
        {
            var result = new List<MyModel>();
            result.Add(ParseItem(Ex1));
            result.Add(ParseItem(Ex2));
            result.Add(ParseItem(Ex3));
        }

        private static MyModel ParseItem(string example)
        {
            var columnSplit = example.Split((char[]) null, StringSplitOptions.RemoveEmptyEntries);

            int index = -1;
            string interfaceType = string.Empty;
            long size = -1;
            string model = string.Empty;

            if (columnSplit.Count() == 4)
            {
                //direct match (no spaces in input)
                index = Convert.ToInt32(columnSplit[0]);
                interfaceType = columnSplit[1];
                model = columnSplit[2];
                size = Convert.ToInt64(columnSplit[3]);
            }
            else
            {
                string modelDescription = string.Empty;

                for (int i = 0; i < columnSplit.Count(); i++)
                {
                    if (i == 0)
                    {
                        index = Convert.ToInt32(columnSplit[i]);
                    }
                    else if (i == 1)
                    {
                        interfaceType = columnSplit[i];
                    }
                    else if (i == columnSplit.Count() - 1) //last
                    {
                        size = Convert.ToInt64(columnSplit[i]);
                    }
                    else
                    {
                        //build the model
                        modelDescription += columnSplit[i] + ' ';
                    }
                }

                model = modelDescription.TrimEnd();
            }

            var myItem = BuildResultItem(index, interfaceType, model, size);
            return myItem;
        }

        private static MyModel BuildResultItem(int index, string interfaceType, string model, long size)
        {
            var myItem = new MyModel
            {
                Index = index,
                InterfaceType = interfaceType,
                Model = model,
                Size = size
            };

            return myItem;
        }

        private class MyModel
        {
            public int Index { get; set; }
            public string InterfaceType { get; set; }
            public string Model { get; set; }
            public long Size { get; set; }
        }
    }
}

This answer follows the facts from my comment: there will always be 4 columns, the first and last column will always be a numeric, and builds up from there.

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

Comments

0

It appears that the command you run ensures a double-space between each column. It's then a matter of doing a string split on double strings only.

So, given your string s then this works for me:

var map =
    s
        .Split(Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries)
        .Skip(1)
        .Select(x => x.Split(new [] { "  " }, StringSplitOptions.RemoveEmptyEntries))
        .Select(x => x.Select(y => y.Trim()).ToArray())
        .ToDictionary(
            x => int.Parse(x[0]),
            x => new
            {
                InterfaceType = x[1],
                Model = x[2],
                Size = ulong.Parse(x[3]),
            });

I can then do:

string it = map[0].InterfaceType;
ulong size = map[2].Size;

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.