Class For Parsing Windows Command Line

This is more of a snippet for myself. This is useful for parsing command lines for Windows Console applications and I have written code like this many times over. This class parses command lines of the form:

someprogram.exe /<switch0>:<switch0 value> /<switch1> /<switch2>:<switch2 value enclosed in quotes>

An example would be:

foo.exe /source:"C:\temp\path with spaces" /source:C:\temp\foo /dest:C:\DestFolder /c /o

Note the duplicate entry for /source. This class supports the same switch appearing multiple times.

[code language=”csharp”]
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;

namespace ConParse
{
/// <summary>
/// This class will parse a Windows console application command line.
/// <remarks>
/// Switches are entered in the form
/// Example: YourProgram.exe /switchname:&quot;switch value with spaces in quotes&quot; /f /sec:90 /src:C:\temp /src:"C:\temp\foo dir"
/// Switches start with / followed by a single character or string token for the switch. Switches with values are followed by a colon :.
/// Values with spaces in them are enclosed in quotes. A particulare switch may be entered more than once.
/// </remarks>
/// </summary>
public class CArgs : Dictionary<string, List<string>>
{
/* Without excaped quotes, the Regex looks like the following below.
(?<=/) (?<sw>\w+)
(?<co>:)? (?(co) (?<qu>")?
(?(qu) (?<arg> [^"]+)" | (?<arg> \S+) )
)
*/

// pattern to parse the command line
private const string _PATTERN = @"(?<=/) (?<sw>\w+)
(?<co>:)? (?(co) (?<qu>"")?
(?(qu) (?<arg> [^""]+)"" | (?<arg> \S+) )
) ";

/// <summary>
/// Constructor, parses the command line and populates the dictionary.
/// </summary>
public CArgs()
{

// get complete command line
string sCmdLine = Environment.CommandLine;

// sanity check, should never be true
if (string.IsNullOrEmpty(sCmdLine))
return;

// we get the name of the program at the beginning of the command line. This we want to strip out
string[] args = Environment.GetCommandLineArgs();

// sanity check, these should never be true
if (null == args)
return;

// other sanity check, should not be true
if (args.Length < 1)
return;

// first arg is the path to the program
string arg0 = args[0];
if (!string.IsNullOrEmpty(arg0))
{
int startAt = arg0.Length;

// the command line may being with a quote for an exe in a path with spaces, args[0] will no have the quotes
if (sCmdLine.StartsWith("\""))
startAt += 2;

// strip out the exe part
sCmdLine = sCmdLine.Substring(startAt);
}

// parse the command line switches
Match mt = Regex.Match(sCmdLine, _PATTERN, RegexOptions.IgnorePatternWhitespace | RegexOptions.Singleline);
string sw = null;
string sarg = null;
List<string> vals = null;
while (mt.Success)
{
sw = mt.Groups["sw"].Value;
sarg = mt.Groups["arg"].Value;

if (this.ContainsKey(sw))
{
vals = this[sw];
}
else
{
vals = new List<string>();
this[sw] = vals;
}

//switches without values will have empty string values.
vals.Add(sarg ?? string.Empty);

mt = mt.NextMatch();
}
}
}
}

[/code]

This entry was posted in C#, Code Samples and tagged . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *