share
Stack OverflowBest way to parse command line arguments in C#?
[+731] [20] Paul Stovell
[2009-01-29 13:33:28]
[ c# .net command-line-arguments ]
[ https://stackoverflow.com/questions/491595/best-way-to-parse-command-line-arguments-in-c ]

When building console applications that take parameters, you can use the arguments passed to Main(string[] args).

In the past I've simply indexed/looped that array and done a few regular expressions to extract the values. However, when the commands get more complicated, the parsing can get pretty ugly.

So I'm interested in:

Assume the commands always adhere to common standards such as answered here [1].

A previous discussion, split-string-containing-command-line-parameters-into-string-‌​in-c#, may have some answers. - gimel
(1) Hi, sorry it's a bit off-topic. however I do use the "Application Settings" to pass argument to the application. I found it quite easy to use and no need to write argument/file parsing,and no need for extra library. msdn.microsoft.com/en-us/library/aa730869(VS.80).aspx - call me Steve
(44) @call me Steve: the point of command line arguments is that they can vary per call - how do you do that with application settings? - reinierpost
[+324] [2010-01-14 22:06:25] jonp [ACCEPTED]

I would strongly suggest using NDesk.Options [1] ( Documentation [2]) and/or Mono.Options [3] (same API, different namespace). An example from the documentation [4]:

bool show_help = false;
List<string> names = new List<string> ();
int repeat = 1;

var p = new OptionSet () {
    { "n|name=", "the {NAME} of someone to greet.",
       v => names.Add (v) },
    { "r|repeat=", 
       "the number of {TIMES} to repeat the greeting.\n" + 
          "this must be an integer.",
        (int v) => repeat = v },
    { "v", "increase debug message verbosity",
       v => { if (v != null) ++verbosity; } },
    { "h|help",  "show this message and exit", 
       v => show_help = v != null },
};

List<string> extra;
try {
    extra = p.Parse (args);
}
catch (OptionException e) {
    Console.Write ("greet: ");
    Console.WriteLine (e.Message);
    Console.WriteLine ("Try `greet --help' for more information.");
    return;
}
[1] http://www.ndesk.org/Options
[2] http://www.ndesk.org/doc/ndesk-options/
[3] https://github.com/mono/mono/blob/master/mcs/class/Mono.Options/Mono.Options/Options.cs
[4] http://www.ndesk.org/doc/ndesk-options/NDesk.Options/OptionSet.html#T:NDesk.Options.OptionSet:Docs:Example:1

(14) NDesk.options is great, but doesn't seem to really support console apps with more than one distinct command well. If you want that, try ManyConsole which builds on NDesk.Options: nuget.org/List/Packages/ManyConsole - Frank Schwieterman
(5) When I have one app with multiple distinct commands, I "layer" the OptionSets. Take mdoc (docs.go-mono.com/index.aspx?link=man%3amdoc%281%29), which has a "global" OptionSet (github.com/mono/mono/blob/master/mcs/tools/mdoc/…) which delegates to a per-command OptionSet (e.g. github.com/mono/mono/blob/master/mcs/tools/mdoc/…) - jonp
(3) NDesk no work for me. Could read integer arguments ok but not strings. The variables keep getting the arguments (e.g. 's','a', etc ) instead of the argument values (e.g. 'serverName', 'ApplicationName'). Gave up and used 'Command Line Parser Library' instead. Ok so far. - Jay
My favourite point about this is that its a single .cs file that you can add to your project - there is no need to reference / ship external assemblies. - Justin
Not sure I understand the popularity of NDesk.Options. That initializer would be a mess for a program with anything more that say 50+ options/arguments. But it uses lambdas, initializers etc so I guess it must be better! - Ash
(2) @AshleyHenderson For one thing, it's small and flexible. Most solutions only work with optional named arguments (i.e., cannot do like git checkout master), or their arguments are not flexible (i.e., doesn't support --foo 123 = --foo=123 = -f 123= -f=123 and also -v -h = -vh). - Wernight
(1) @FrankSchwieterman that should be its own answer. And thanks for the tip, ManyConsole is a real treat, fits perfectly for me. - quentin-starin
thanks qes! The topic is closed though, thats fine though a top-comment on the selected answer is going to get word out as well as a lower ranked answer. - Frank Schwieterman
It's good because it's flexible and support many standard ways. However you will have to check for missing parameters, parameter used more than once, additional parameters provided, and invalid parameter values. My wish is that when you raise an exception in an OptionSet lamba it raises a OptionException automatically. Also there is no easy way to reach the author or enrich the source code. - Wernight
1
[+197] [2011-09-07 07:29:53] Adrian Grigore

I really like the Command Line Parser Library ( http://commandline.codeplex.com/ ). It has a very simple and elegant way of setting up parameters via attributes:

class Options
{
    [Option("i", "input", Required = true, HelpText = "Input file to read.")]
    public string InputFile { get; set; }

    [Option(null, "length", HelpText = "The maximum number of bytes to process.")]
    public int MaximumLenght { get; set; }

    [Option("v", null, HelpText = "Print details during execution.")]
    public bool Verbose { get; set; }

    [HelpOption(HelpText = "Display this help screen.")]
    public string GetUsage()
    {
        var usage = new StringBuilder();
        usage.AppendLine("Quickstart Application 1.0");
        usage.AppendLine("Read user manual for usage instructions...");
        return usage.ToString();
    }
}

(6) This is the library that I settled on as well. I am writing applications for a large company which need to be maintained for many years -- this library has been continuously updated since 2005, seems to be popular, is written by people active in the C# community, and is licensed in BSD style in case support does vanish. - Charles Burns
I recommend this also. My only problem was: Specifying allowed arguement combination (Eg if had move arguement must have source and dest arguments also) may be possible to do with attributes. But you maybe better off doing it with seperate Argument validator logic - Frames Catherine White
(1) I like the Options class. It seems to support unnamed parameters and flags like --recursive too. - Wernight
(2) I have just tested it and I have implemented option for my application in just few minutes. It is extremely simple to use library. - Trismegistos
(3) I found this library very restrictive for myself. If you need exclusive sets, you cannot define required options for each set, so have to check them manually. You cannot define min requirement for unnamed values, you have to check them manually as well. Help screen builder also not flexible at all. If behavior of the library doesn't fit your needs out of box, you can do virtually nothing to change it. - Sergey Kostrukov
2
[+50] [2009-01-29 14:12:55] user7116

The WPF TestApi library [1] comes with one of the nicest command line parsers for C# development. I highly recommend looking into it, from Ivo Manolov's blog on the API [2]:

// EXAMPLE #2:
// Sample for parsing the following command-line:
// Test.exe /verbose /runId=10
// This sample declares a class in which the strongly-
// typed arguments are populated
public class CommandLineArguments
{
   bool? Verbose { get; set; }
   int? RunId { get; set; }
}

CommandLineArguments a = new CommandLineArguments();
CommandLineParser.ParseArguments(args, a);
[1] http://www.codeplex.com/TestApi
[2] http://blogs.msdn.com/ivo_manolov/archive/2008/12/17/9230331.aspx

(19) +1. Command-line parsing is something really should come from the vendor (ie Microsoft) rather than via a 3rd party tool, even if the vendor's support comes in a round-about manner. - Joel Coehoorn
(2) That said, the accepted answer (mono) is the next best thing. - Joel Coehoorn
(6) @Joel, what part is that important that command line parsing has to be from vendor? What are your reasons? - greenoldman
(3) @marcias: I think he means it probably should have been Out of the Box...like a lot of things :) - user7116
The library is huge! Contains so much more than I need ... - Riri
One problem with this, is that it's GPL-incompatible (released under MSPL)... Or am I missing something? - Tao
Can this handle spaces in the parameter values? I just got it, wired it up, and can't figure out how to deal with spaces. Ex: /MyValue="The Brown Fox" (I put quotes around it as first attempt) - granadaCoder
3
[+24] [2009-01-29 13:40:58] abatishchev
(2) NDesk options has a very nice API - user35149
(2) I will add another vote for NDesk it works well, is non-intrusive and well documented. - Terence
(1) Mono.GetOptions is very old, NDesk.Options is much nicer (or Mono.Options if you prefer, its the same class, here: anonsvn.mono-project.com/source/trunk/mcs/class/Mono.Options‌​/… ) - Matt Enright
@Matt, Yea, it is. My question is very old too. One year and one week old :) - abatishchev
(7) @Adam Oren: my answer is 1 year and 1 month old! mono trunk's structure was refactored. That code is now placed to anonsvn.mono-project.com/viewvc/branches/mono-2-2/mcs/class/‌​… - abatishchev
(6) @Tormod: it's Mono.GetOptions which is obsolete, not Mono.Options. Mono.Options is still maintained. - jonp
4
[+14] [2010-07-01 01:03:02] Brian

Looks like everybody has their own pet command-line parsers, figure I had better add mine as well :).

http://bizark.codeplex.com/

This library contains a command-line parser [1] that will initialize a class with the values from the command-line. It has a ton of features (I've been building it up over many years).

From the documentation [2]...

Command-line parsing in the BizArk framework has these key features:

  • Automatic initialization: Class properties are automatically set based on the command-line arguments.
  • Default properties: Send in a value without specifying the property name.
  • Value conversion: Uses the powerful ConvertEx class also included in BizArk to convert values to the proper type.
  • Boolean flags: Flags can be specified by simply using the argument (ex, /b for true and /b- for false) or by adding the value true/false, yes/no, etc.
  • Argument arrays: Simply add multiple values after the command-line name to set a property that is defined as an array. Ex, /x 1 2 3 will populate x with the array { 1, 2, 3 } (assuming x is defined as an array of integers).
  • Command-line aliases: A property can support multiple command-line aliases for it. For example, Help uses the alias ?.
  • Partial name recognition: You don’t need to spell out the full name or alias, just spell enough for the parser to disambiguate the property/alias from the others.
  • Supports ClickOnce: Can initialize properties even when they are specified as the query string in a URL for ClickOnce deployed applications. The command-line initialization method will detect if it is running as ClickOnce or not so your code doesn’t need to change when using it.
  • Automatically creates /? help: This includes nice formatting that takes into account the width of the console.
  • Load/Save command-line arguments to a file: This is especially useful if you have multiple large, complex sets of command-line arguments that you want to run multiple times.
[1] http://bizark.codeplex.com/wikipage?title=Command-line%20Parsing&referringTitle=Home
[2] http://bizark.codeplex.com/wikipage?title=Command-line%20Parsing&referringTitle=Home

(2) I found BizArk's command-line parser much more easier and fluent than others. Highly recommended! - Boris Modylevsky
5
[+13] [2009-12-15 07:07:43] PeterH

I wrote a C# command line argument parser a while back. Its at: http://www.codeplex.com/CommandLineArguments


6
[+9] [2012-03-15 15:11:25] Colonel Panic

CLAP [1] (command line argument parser) has a usable API and is wonderfully documented. You make a method, annotating the parameters. https://github.com/adrianaisemberg/CLAP

[1] http://adrianaisemberg.github.com/CLAP/

(2) It's very simple to use and their website rocks. Their syntax however isn't very intuitive: myapp myverb -argname argvalue (must have -argname) or myapp -help (commonly --help). - Wernight
@Wernight you can use the IsDefault parameter on the Verb do that it can be omitted. I didn't found support for positional parameters, but I did only use positional parameters when I was parsing the command line myself. It's much clearer to use named arguments followed by values IMHO. - Loudenvier
7
[+5] [2010-05-11 18:25:59] csharptest.net

There are numerous solutions to this problem. For completeness and to provide the alternative if someone desires I'm adding this answer for two useful classes in my google code library [1].

The first is ArgumentList which is responsible only for parsing command line parameters. It collects name-value pairs defined by switches '/x:y' or '-x=y' and also collects a list of 'unnamed' entries. It's basic usage is discussed here [2], view the class here [3].

The second part of this is the CommandInterpreter [4] which creates a fully-functional command-line application out of your .Net class. As an example:

using CSharpTest.Net.Commands;
static class Program
{
    static void Main(string[] args)
    {
        new CommandInterpreter(new Commands()).Run(args);
    }
    //example ‘Commands’ class:
    class Commands
    {
        public int SomeValue { get; set; }
        public void DoSomething(string svalue, int ivalue)
        { ... }

With the above example code you can run the following:

Program.exe DoSomething "string value" 5

-- or --

Program.exe dosomething /ivalue=5 -svalue:"string value"

It's as simple as that or as complex as you need it to be. You can review the source code [5], view the help [6], or download the binary [7].

[1] http://code.google.com/p/csharptest-net/
[2] http://csharptest.net/?p=87
[3] http://csharptest.net/browse/trunk/src/Shared/ArgumentList.cs
[4] http://csharptest.net/?p=299
[5] http://csharptest.net/browse/src/Library/Commands
[6] http://help.csharptest.net/?CSharpTest.Net.Library~CSharpTest.Net.Commands_namespace.html
[7] http://code.google.com/p/csharptest-net/downloads/list

8
[+4] [2009-01-29 13:43:09] Xn0vv3r

I like that one [1], because you can "define rules" for the arguments, needed or not,...

or if you're a Unix guy, than you might like the GNU Getopt .NET [2] port.

[1] http://www.codeproject.com/KB/recipes/plossum_commandline.aspx
[2] http://www.codeplex.com/getopt

9
[+4] [2012-01-23 16:55:08] Phill Tew

You may like my one Rug.Cmd [1]

Easy to use and expandable command line argument parser. Handles: Bool, Plus / Minus, String, String List, CSV, Enumeration.

Built in '/?' help mode.

Built in '/??' and '/?D' document generator modes.

static void Main(string[] args) 
{            
    // create the argument parser
    ArgumentParser parser = new ArgumentParser("ArgumentExample", "Example of argument parsing");

    // create the argument for a string
    StringArgument StringArg = new StringArgument("String", "Example string argument", "This argument demonstrates string arguments");

    // add the argument to the parser 
    parser.Add("/", "String", StringArg);

    // parse arguemnts
    parser.Parse(args);

    // did the parser detect a /? argument 
    if (parser.HelpMode == false) 
    {
        // was the string argument defined 
        if (StringArg.Defined == true)
        {
            // write its value
            RC.WriteLine("String argument was defined");
            RC.WriteLine(StringArg.Value);
        }
    }
}

Edit: This is my project and as such this answer should not be seen as an endorsement from a third party. That said I do use it for every command line based program I write, it is open source and it is my hope that others may benefit from it.

[1] http://cmd.codeplex.com

Just an FYI, that you should put a little disclaimer that you are affiliated with the Rug.Cmd project (as mentioned in the FAQ): stackoverflow.com/faq#promotion -- Not a big deal since you're promoting an open-source project, but it is still good to add a disclaimer ;) +1 by the way... looks pretty well done. - Jason Down
Cheers for pointing that out and thanks for the +1, I will make sure I'm more explicit about my affiliation. - Phill Tew
No worries... there are some sticklers out there for this type of thing (I'm not one of them), so I like to give people a heads up. Again, not usually a problem for open source projects. It's mostly to stop people from spamming recommendations for their (paid) products. - Jason Down
10
[+3] [2009-04-17 21:28:20] jerome

There is a command line argument parser at http://www.codeplex.com/commonlibrarynet

It can parse arguments using
1. attributes
2. explicit calls
3. single line of multiple arguments OR string array

It can handle things like the following:

-config:Qa -startdate:${today} -region:'New York' Settings01

It's very easy to use.


11
[+2] [2009-08-21 07:27:24] Chris S

This is a handler I wrote based on the Novell Options class.

This one is aimed at console applications that execute a while (input !="exit") style loop, an interactive console such as an FTP console for example.

Example usage:

static void Main(string[] args)
{
    // Setup
    CommandHandler handler = new CommandHandler();
    CommandOptions options = new CommandOptions();

    // Add some commands. Use the v syntax for passing arguments
    options.Add("show", handler.Show)
        .Add("connect", v => handler.Connect(v))
        .Add("dir", handler.Dir);

    // Read lines
    System.Console.Write(">");
    string input = System.Console.ReadLine();

    while (input != "quit" && input != "exit")
    {
        if (input == "cls" || input == "clear")
        {
            System.Console.Clear();
        }
        else
        {
            if (!string.IsNullOrEmpty(input))
            {
                if (options.Parse(input))
                {
                    System.Console.WriteLine(handler.OutputMessage);
                }
                else
                {
                    System.Console.WriteLine("I didn't understand that command");
                }

            }

        }

        System.Console.Write(">");
        input = System.Console.ReadLine();
    }
}

And the source:

/// <summary>
/// A class for parsing commands inside a tool. Based on Novell Options class (http://www.ndesk.org/Options).
/// </summary>
public class CommandOptions
{
    private Dictionary<string, Action<string[]>> _actions;
    private Dictionary<string, Action> _actionsNoParams;

    /// <summary>
    /// Initializes a new instance of the <see cref="CommandOptions"/> class.
    /// </summary>
    public CommandOptions()
    {
        _actions = new Dictionary<string, Action<string[]>>();
        _actionsNoParams = new Dictionary<string, Action>();
    }

    /// <summary>
    /// Adds a command option and an action to perform when the command is found.
    /// </summary>
    /// <param name="name">The name of the command.</param>
    /// <param name="action">An action delegate</param>
    /// <returns>The current CommandOptions instance.</returns>
    public CommandOptions Add(string name, Action action)
    {
        _actionsNoParams.Add(name, action);
        return this;
    }

    /// <summary>
    /// Adds a command option and an action (with parameter) to perform when the command is found.
    /// </summary>
    /// <param name="name">The name of the command.</param>
    /// <param name="action">An action delegate that has one parameter - string[] args.</param>
    /// <returns>The current CommandOptions instance.</returns>
    public CommandOptions Add(string name, Action<string[]> action)
    {
        _actions.Add(name, action);
        return this;
    }

    /// <summary>
    /// Parses the text command and calls any actions associated with the command.
    /// </summary>
    /// <param name="command">The text command, e.g "show databases"</param>
    public bool Parse(string command)
    {
        if (command.IndexOf(" ") == -1)
        {
            // No params
            foreach (string key in _actionsNoParams.Keys)
            {
                if (command == key)
                {
                    _actionsNoParams[key].Invoke();
                    return true;
                }
            }
        }
        else
        {
            // Params
            foreach (string key in _actions.Keys)
            {
                if (command.StartsWith(key) && command.Length > key.Length)
                {

                    string options = command.Substring(key.Length);
                    options = options.Trim();
                    string[] parts = options.Split(' ');
                    _actions[key].Invoke(parts);
                    return true;
                }
            }
        }

        return false;
    }
}

12
[+2] [2011-05-12 06:08:45] Raphael Bossek

My personal favorite is http://www.codeproject.com/KB/recipes/plossum_commandline.aspx by Peter Palotas:

[CommandLineManager(ApplicationName="Hello World",
    Copyright="Copyright (c) Peter Palotas")]
class Options
{
   [CommandLineOption(Description="Displays this help text")]
   public bool Help = false;

   [CommandLineOption(Description = "Specifies the input file", MinOccurs=1)]
   public string Name
   {
      get { return mName; }
      set
      {
         if (String.IsNullOrEmpty(value))
            throw new InvalidOptionValueException(
                "The name must not be empty", false);
         mName = value;
      }
   }

   private string mName;
}

13
[+2] [2011-06-11 06:50:37] Cristian Lupascu

I recently came across The FubuCore Command line parsing implementation I really like it, the reasons being:

  • it's easy to use - although I couldn't find a documentation for it, the FubuCore solution also provides a project containing a nice set of Unit Tests that speak more about the functionality than any documentation could
  • it has a nice object oriented design, no code repetition or other such things that I used to have in my command line parsing apps
  • it's declarative: you basically write classes for the Commands and sets of parameters and decorate them with attributes to set various options (e.g. name, description, mandatory/optional)
  • the library even prints a nice Usage Graph, based on these definitions

Below is a simple example on how to use this. To illustrate the usage, I've written a simple utility that has two commands: - add (adds an object to a list - an object consists of a name(string), value(int) and a boolean flag) - list (lists all the currently added objects)

First of all, I wrote a Command class for the 'add' command:

[Usage("add", "Adds an object to the list")]
[CommandDescription("Add object", Name = "add")]
public class AddCommand : FubuCommand<CommandInput>
{
    public override bool Execute(CommandInput input)
    {
        State.Objects.Add(input); // add the new object to an in-memory collection

        return true;
    }
}

This command takes a CommandInput instance as parameter, so I define that next:

public class CommandInput
{
    [RequiredUsage("add"), Description("The name of the object to add")]
    public string ObjectName { get; set; }

    [ValidUsage("add")]
    [Description("The value of the object to add")]
    public int ObjectValue { get; set; }

    [Description("Multiply the value by -1")]
    [ValidUsage("add")]
    [FlagAlias("nv")]
    public bool NegateValueFlag { get; set; }
}

The next command is 'list', which is implemented as follows:

[Usage("list", "List the objects we have so far")]
[CommandDescription("List objects", Name = "list")]
public class ListCommand : FubuCommand<NullInput>
{
    public override bool Execute(NullInput input)
    {
        State.Objects.ForEach(Console.WriteLine);

        return false;
    }
}

The 'list' command takes no parameters, so I defined a NullInput class for this:

public class NullInput { }

All that's left now is to wire this up in the Main() method, like this:

    static void Main(string[] args)
    {
        var factory = new CommandFactory();
        factory.RegisterCommands(typeof(Program).Assembly);

        var executor = new CommandExecutor(factory);

        executor.Execute(args);
    }

The program works as expected, printing hints about the correct usage in case any commands are invalid:

  ------------------------
    Available commands:
  ------------------------
     add -> Add object
    list -> List objects
  ------------------------

And a sample usage for the 'add' command:

Usages for 'add' (Add object)
  add <objectname> [-nv]

  -------------------------------------------------
    Arguments
  -------------------------------------------------
     objectname -> The name of the object to add
    objectvalue -> The value of the object to add
  -------------------------------------------------

  -------------------------------------
    Flags
  -------------------------------------
    [-nv] -> Multiply the value by -1
  -------------------------------------

14
[+2] [2012-07-07 05:07:43] hannasm

Powershell Commandlets.

Parsing done by powershell based on attributes specified on the commandlets, support for validations, parameter sets, pipelining, error reporting, help, and best of all returning .NET objects for use in other commandlets.

A couple links i found helpful getting started:

[1] http://blogs.msdn.com/b/saveenr/archive/2010/03/08/how-to-create-a-powershell-2-0-module-and-cmdlet-with-visual-studio-2010-screencast-included.aspx
[2] http://msdn.microsoft.com/en-us/library/ms569889%28v=vs.85%29
[3] http://msdn.microsoft.com/en-us/library/dd878268%28v=vs.85%29

15
[+2] [2012-08-11 15:02:34] Bernard

C# CLI [1] is a very simple command-line argument parsing library that I wrote. It's well-documented and open source.

[1] http://sourceforge.net/projects/ccli

Well documented? Where is the documentation? - Suhas
There is internal documentation (i.e. in the codebase) as well as external documentation (see the Readme.mkd file in the Documentation folder). - Bernard
Ok, I commented hastily. May be you could move your project to github and your documentation automatically starts appearing on the home page. - Suhas
16
[+1] [2009-08-21 11:07:24] devdimi

Genghis Command Line Parser [1] may be a little out of date, but it is very feature complete and works pretty well for me.

[1] http://www.sellsbrothers.com/tools/genghis/

Sad, but Genghis Command Line Parser does not have any documentation. - okigan
If you look at the sources there is sample that shows usage options. genghis.codeplex.com/SourceControl/changeset/view/9491#73699 - devdimi
17
[0] [2010-07-23 14:09:11] Stuart Lange

I would suggest the open-source library CSharpOptParse [1]. It parses the command line and hydrates a user-defined .NET object with the command-line input. I always turn to this library when writing a C# console application.

[1] http://sourceforge.net/projects/csharpoptparse/

18
[0] [2011-06-28 09:04:55] Andreas

Please use the .net port of the apache commons cli API. This works great.

http://sourceforge.net/projects/dotnetcli/

and the original API for concepts and introduction

http://commons.apache.org/cli/


19
[0] [2011-06-29 12:43:58] Martin Lütken

A very simple easy to use ad hoc class for command line parsing, that supports default arguments.

class CommandLineArgs
{
    public static CommandLineArgs I
    {
        get
        {
            return m_instance;
        }
    }

    public  string argAsString( string argName )
    {
        if (m_args.ContainsKey(argName)) {
            return m_args[argName];
        }
        else return "";
    }

    public long argAsLong(string argName)
    {
        if (m_args.ContainsKey(argName))
        {
            return Convert.ToInt64(m_args[argName]);
        }
        else return 0;
    }

    public double argAsDouble(string argName)
    {
        if (m_args.ContainsKey(argName))
        {
            return Convert.ToDouble(m_args[argName]);
        }
        else return 0;
    }

    public void parseArgs(string[] args, string defaultArgs )
    {
        m_args = new Dictionary<string, string>();
        parseDefaults(defaultArgs );

        foreach (string arg in args)
        {
            string[] words = arg.Split('=');
            m_args[words[0]] = words[1];
        }
    }

    private void parseDefaults(string defaultArgs )
    {
        if ( defaultArgs == "" ) return;
        string[] args = defaultArgs.Split(';');

        foreach (string arg in args)
        {
            string[] words = arg.Split('=');
            m_args[words[0]] = words[1];
        }
    }

    private Dictionary<string, string> m_args = null;
    static readonly CommandLineArgs m_instance = new CommandLineArgs();
}

class Program
{
    static void Main(string[] args)
    {
        CommandLineArgs.I.parseArgs(args, "myStringArg=defaultVal;someLong=12");
        Console.WriteLine("Arg myStringArg  : '{0}' ", CommandLineArgs.I.argAsString("myStringArg"));
        Console.WriteLine("Arg someLong     : '{0}' ", CommandLineArgs.I.argAsLong("someLong"));
    }
}

20