Click here to Skip to main content
12,697,340 members (28,790 online)
Click here to Skip to main content
Add your own
alternative version

Tagged as


59 bookmarked

Lightweight C# Command Line Parser

, 19 Aug 2009 CPOL
Rate this:
Please Sign up or sign in to vote.
A lightweight command line parsing solution in C#.


This lightweight implementation approach of a command line parser is small enough to fit in one C# file. It is complete enough that it covers most of the common command line parsing tasks:

  • 'Unlimited' number of Option Alias Names (e.g., for '-verbose', you can add these aliases: '-v', '/v', '/verbose', ..).
  • Supports options starting with '-' or '/'.
  • Supports option and parameter attached in one argument (e.g., -P=123 ).
  • Or as an argument pair (e.g./ -P 123).
  • Basic 'String', 'Integer', and 'Double' parameter options support.
  • Intelligently handles different number decimal separators.
  • Contains a basic usage (help) message of the available (registered) options.

but stays simple enough that it can be extended or changed.


Looking for a command line parsing solution, I found that the existing approaches could be separated into two categories:

  1. Very simple or specialized solutions, or
  2. rather heavy weight solutions.

I missed a lightweight approach that is complete enough as a ready to use solution for quick jobs and extensible enough that it provides a solid base for extensions and changes.

The reason for more complete solutions to have the tendency to be heavy weight come from the complexity of parameter type conversion. Although it is very tempting to try to provide a solution for all different object types for 'option parameters', a better and more modern approach is to use 'method injection' to make it easy to create and add your own custom options.

An example

//create parser
CMDLineParser parser = new CMDLineParser();

//add Options to parse
CMDLineParser.Option DebugOpt = 
  parser.AddBoolSwitch("-Debug", "Print Debug information");

//add an alias

CMDLineParser.NumberOption NumOpt = parser.AddDoubleParameter("-NegNum=", 
                                    "A required negativ Number", true);

  //parse the command line
catch (CMDLineParser.CMDLineParseException ex)
  //show available options      
  Console.WriteLine("Error: " + ex.Message);

//show debug information if set
if (DebugOpt.isMatched) parser.Debug();       

//replace argument list with remaining arguments
args = parser.RemainingArgs();

double num = NumOpt.Value;

In a Windows application, you do not have a console window. In that case, you may want to replace 'Console.WriteLine(..)' with 'System.Windows.Forms.MessageBox.Show(..)'.

Dealing with invalid command line arguments

The following basic 'Exceptions' can occur while parsing the command line:

MissingRequiredOptionExceptionA required option was not detected.
DuplicateOptionExceptionA duplicate option was detected: this is an exception because a duplicate would override a previously set parameter!
ParameterConversionExceptionTrying to convert an option parameter to a specified data type (e.g., double value) failed.
InvalidOptionsExceptionInvalid, not registered options have been detected.

An 'InvalidOptionsException' is only thrown when:

parser.throwInvalidOptionsException = true;

It is also possible to disable the collection of invalid (not recognized) options:

parser.collectInvalidOptions = false;

leaving these options in the remaining arguments list:

args = parser.RemainingArgs();

For simplicity, all described exceptions can be caught using the base class CMDLineParser.CMDLineParseException, as in the above example.

Note that in a 'NumberOption' like "-Num -16.5", the second argument will not be confused with an invalid command line option but will be identified as a parameter.

For those who just want to use the solution, this is probably all you need to know.


Command line parsing can be separated into two problem areas:

  1. Identification of options and option parameters on the command line.
  2. Handling (type conversion) of parameter values (e.g., a double number).

The first point is a core feature of every command line parser. Regarding the second point, it could be questioned if converting parameters to different types or objects is better done through sub classing or by the application itself, instead of designing it as a core part of the command line parser. For example, a useful idea is to pass the format information for a specific parameter as a second parameter and use this information to do the actual conversion in the 'application context':

-myDate 2002-9-12 -myDateFormat "yyyy-m-dd"

From a good OO design perspective, you might want to 'inject' argument checking in your application (i.e., to expose such a check method to other interfaces) instead of having it hard coded as a part of the command line parser. Therefore, a better strategy than trying to provide an (command line) 'option' solution for every possible object type, and validation possibility which makes the parser solution heavy weight, is a 'method injection' approach. It has the advantage that option parameters can be converted and validated to your own needs.

Creating and adding custom options

Custom options can be created by sub classing CMDLineParser.Option and providing an implementation of object parseValue(string parameter) which does the actual conversion and validation, as in the following example:

class PastDateOption : CMDLineParser.Option
  public PastDateOption(string name, string desription, bool required)
        : base(name, desription, typeof(DateTime), true, required) { }
  //implementation of parseValue
  public override object parseValue(string parameter)
     DateTime date= System.Convert.ToDateTime(parameter);
     DateTime now = DateTime.Now;
     if(date > now)
        throw new System.ArgumentException("Date: " + date + 
                  " is greater then: " + now);
     return date;

Use AddOption(..) to add the new option to the parser:

// create Option
PastDateOption DateOpt = 
  new PastDateOption("-Date","A date in the past",false);
// add the Option to the parser

If a custom option is matched on the command line, parseValue(..) will automatically be called to convert the option parameter and set the option value. In cases of error, it will throw a ParameterConversionException.

Note that in the example above, the date convert function will react dependent on the international settings of your local system.

Globalization issues

For good reason, most of the conversion functions built in C# provide the possibility to pass format information. Making use of a generic approach like Convert.ChangeType(parameter, type) to convert all kinds of parameter data types is tempting, but has the implication that the run time result depends on the international settings of your local system. For numbers, we can provide a more intelligent solution.

Because two different decimal separators are defined in different 'Cultures', converting numbers from the command line makes it necessary to specifically set the 'number format' expected to be passed as a command line parameter when using:

Double.Parse(parameter, _numberstyle, _numberformat);

For the default NumberOption, I intentionally did not make use of the local system setting using the 'CurrentCulture' because it introduces an unnecessary globalization dependency. I remember many years ago (before C#!), how annoying it was if my command line parser did not understand a scientifically computed number (i.e., with "."); eventually, I figured out that it was reacting to my international settings (i.e., it expected ","). A better approach is to use the so called 'invariant Culture' as a default setting:

_numberformat = (new CultureInfo("", false)).NumberFormat;

This setting expects a decimal point "." as a decimal separator (similar to a pocket calculator). However, approximately 50% of the Culture settings (that use Arabic numbers) use a comma "," as a decimal separator symbol.

By simply changing the 'decimal separator' to the separator found in the parameter argument, we can easily provide an implementation that accepts both formats ('.' and ','). This works well as long as NumberStyles.AllowThousands is turned off when parsing numbers. Taking into account that it is quite uncommon to use floating point numbers with 'Thousands' separator on the command line, accepting both formats ('.' and ',') is a more 'Culture Invariant' solution.

In some cases, parsing a specific (globalized) number format is desired. In that case, NumberFormatInfo can be set by creating the NumberOption:

NumberFormatInfo numberformat= (new CultureInfo( "de-DE", false )).NumberFormat;

CMDLineParser.NumberOption NegnumOpt = 
   parser.AddDoubleParameter("-Num", "A Number", 
                             false, numberformat);


Parsing command line arguments is as old a requirement as the existence of console applications. This lightweight, 'one file' implementation aims to support projects or situations in which a lightweight implementation is sufficient.

References and credits

The article Automatic Command Line Parsing in C# by Ray Hayes influenced the creation of this article, so I would like to mention it here. It focuses on automatically creating command line options from class objects via Reflection.

In the Java world, the 'jargs project' has a similar 'lightweight' approach (with a focus on GNU compatible options).


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

In my free time I enjoy playing African percussion.

You may also be interested in...

Comments and Discussions

PraiseThank you Pin
Yevgeni Zolotko16-Apr-16 13:58
memberYevgeni Zolotko16-Apr-16 13:58 
QuestionNot so bad but... Pin
masterluke20-Jan-13 9:22
membermasterluke20-Jan-13 9:22 
GeneralMy vote of 5 Pin
JunfengGuo17-Mar-11 16:01
memberJunfengGuo17-Mar-11 16:01 
GeneralNConsoler Pin
Dima Pasko14-Oct-09 9:50
memberDima Pasko14-Oct-09 9:50 
GeneralRe: NConsoler Pin
cbolti (Christian Bolterauer)15-Oct-09 3:58
membercbolti (Christian Bolterauer)15-Oct-09 3:58 
GeneralNice start Pin
John Whitmire25-Aug-09 5:36
memberJohn Whitmire25-Aug-09 5:36 
GeneralRe: Nice start Pin
cbolti (Christian Bolterauer)26-Aug-09 0:24
membercbolti (Christian Bolterauer)26-Aug-09 0:24 
GeneralRe: Nice start Pin
John Whitmire26-Aug-09 7:23
memberJohn Whitmire26-Aug-09 7:23 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.170118.1 | Last Updated 19 Aug 2009
Article Copyright 2009 by cbolti (Christian Bolterauer)
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid