In todays tutorial we are going to be look at creating a command line parser for your Console Application in C#. More often than not it is needed to pass command line arguments to your application, and doing them in the command line prevents exposing them to the user. When creating a console application you will notice that the Main() you will notice in the signature the parameter args. That parameter is a string array for the command line parameters separated by a space.

The common command line in .Net is pretty restrictive, so I decided to take the time to write my own command line parser. In this tutorial we will look at using creating a custom parser using the RegEx Class of the System.Text.RegularExpressions Namespace. With this parser you can separate your command line parameters with more than just a space. The separators you can use with this parser are
  • -
  • --
  • ,
  • /
So you could have a command line argument like -param1=100 /param2:'100' and both would parse successfully. If you have a good grasp of using Regular Expressions you can modify the pattern I use to use whatever separator you like. In this parser we will take the command line parameters and create a string collection of key/value pairs and store them in a StringDictionary.

This parsing is done using Regular Expressions. We have 2 patters we will be using
  • ^-{1,2}|^/|=|: - Splits parameters into key/value pairs
  • ^['""]?(.*?)['""]?$ - Remove any trailing or starting quotes or double quotes
This is a fairly simple class, it has a single constructor, and an indexer. The constructor is where all the work happens.

We first create a new StringDictionary which will hold our key/value pairs, which are strongly typed as strings instead of objects.


csharp

//create our stringDictionary Object for holding
//the resulting key/value pairs
parameters = new StringDictionary();


From there we create 2 RegEx objects, one for splitting the arguments and one for removing trailing and leading single or double quotes.


csharp

//create a RegEx Object for splitting the parameters
Regex paramSplit = new Regex(@"^-{1,2}|^/|=|:", RegexOptions.IgnoreCase | RegexOptions.Compiled);

//create a RegEx Object for removing trailing &
//leading single and double quotes
Regex paramRemover = new Regex(@"^['""]?(.*?)['""]?$", RegexOptions.IgnoreCase | RegexOptions.Compiled);




We Then loop through each item in the initial command line array and split it using our RegEx Object. While in the loop we use a switch Statement on the length of the resulting array. We then add each key/value pair to our StringDictionary object


csharp

foreach (string str in arguments)
{
//split the parameter array
paramParts = paramSplit.Split(str, 3);
//use a switch statement to tell the parser what
//to do for each possible length of the array
switch (paramParts.Length)
{
case 1:
if (param != null)
{
if (!parameters.ContainsKey(param))
{
paramParts[0] = paramRemover.Replace(paramParts[0], "$1");
parameters.Add(param, paramParts[0]);
}
param = null;
}
break;
//here we found just a parameter
case 2:
// The last parameter is still waiting.
// With no value, set it to true.
if (param != null)
{
if (!parameters.ContainsKey(param))
parameters.Add(param, "true");
}
param = paramParts[1];
break;
//here we found a parameter with a value
case 3:
// The last parameter is still waiting.
// With no value, set it to true.
if (param != null)
{
if (!parameters.ContainsKey(param))
parameters.Add(param, "true");
}
param = paramParts[1];
// Remove possible enclosing characters (",')
if (!parameters.ContainsKey(param))
{
paramParts[2] = paramRemover.Replace(paramParts[2], "$1");
parameters.Add(param, paramParts[2]);
}
param = null;
break;
}
}



Before ending our constructor, we check one last time to ensure there are no parameters waiting to be added to our StringDictionary, if there is we then add the remaining parameters


csharp

// In case a parameter is still waiting
if (param != null)
{
if (!(parameters.ContainsKey(param)))
{
parameters.Add(param, "true");
}
}



The indexer for our parser simply retrieves the value of a parameter based on the key provided


csharp

/// <summary>
/// indexer to retrieve the parameters value if it exists
/// </summary>
/// <param name="param">parameter we want the value for</param>
/// <returns></returns>
public string this[string param]
{
get
{
return (parameters[param]);
}
}


So now lets look at our parser class in it's entirety


csharp

using System;
using System.Collections.Specialized;
using System.Text.RegularExpressions;

//****************************************************************************
// LICENSE INFORMATION
//****************************************************************************
// CommandLineParser Version 1.0.0.0
// Class file for parsing command line parameters
//
// Copyright © 2008
// Richard L. McCutchen
// Created: 31MAR08
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//*****************************************************************************

namespace Parser
{
public class CommandLineParser
{
private StringDictionary parameters;

public CommandLineParser(string[] arguments)
{
//create our stringDictionary Object for holding
//the resulting key/value pairs
parameters = new StringDictionary();

//create a RegEx Object for splitting the parameters
Regex paramSplit = new Regex(@"^-{1,2}|^/|=|:", RegexOptions.IgnoreCase | RegexOptions.Compiled);

//create a RegEx Object for removing trailing &
//leading single and double quotes
Regex paramRemover = new Regex(@"^['""]?(.*?)['""]?$", RegexOptions.IgnoreCase | RegexOptions.Compiled);

string param = null;
string[] paramParts;
//loop through each item in the arguments array
foreach (string str in arguments)
{
//split the parameter array
paramParts = paramSplit.Split(str, 3);
//use a switch statement to tell the parser what
//to do for each possible length of the array
switch (paramParts.Length)
{
case 1:
if (param != null)
{
if (!parameters.ContainsKey(param))
{
paramParts[0] = paramRemover.Replace(paramParts[0], "$1");
parameters.Add(param, paramParts[0]);
}
param = null;
}
break;
//here we found just a parameter
case 2:
// The last parameter is still waiting.
// With no value, set it to true.
if (param != null)
{
if (!parameters.ContainsKey(param))
parameters.Add(param, "true");
}
param = paramParts[1];
break;
//here we found a parameter with a value
case 3:
// The last parameter is still waiting.
// With no value, set it to true.
if (param != null)
{
if (!parameters.ContainsKey(param))
parameters.Add(param, "true");
}
param = paramParts[1];
// Remove possible enclosing characters (",')
if (!parameters.ContainsKey(param))
{
paramParts[2] = paramRemover.Replace(paramParts[2], "$1");
parameters.Add(param, paramParts[2]);
}
param = null;
break;
}
}
// In case a parameter is still waiting
if (param != null)
{
if (!(parameters.ContainsKey(param)))
{
parameters.Add(param, "true");
}
}
}

/// <summary>
/// indexer to retrieve the parameters value if it exists
/// </summary>
/// <param name="param">parameter we want the value for</param>
/// <returns></returns>
public string this[string param]
{
get
{
return (parameters[param]);
}
}
}
}




Now that we have our parser, how do we use it. Well I'll show you a sample Main method utilizing this new parser class we created


csharp

static void Main(string[] args)
{
//create an instance of the parser
CommandLineParser parser = new CommandLineParser(args);

//now look for a parameter named "param1", if it isnt null then write it's value
//otherwise write "Param1 Not Found!"
if(parser["param1"]!= null) Console.WriteLine("Param1 value: " + parser["param1"]);
else Console.WriteLine("Param1 Not Found!");

// Wait for key
Console.Out.WriteLine("Command Line Arguments Parsed....");
Console.Read();
}
}



In this instance I would pass a command line parameter of Param1="Hello" and the value Param1 Value: Hello would be written to the screen.


Well that's how you create a custom command line arguments parser in C#. I hope you found this tutorial informative and useful, and I thank you for reading smile.gif

Happy Coding!