Click here to Skip to main content
6,933,325 members and growing! (13,669 online)
Email Password   helpLost your password?
 
General Programming » Algorithms & Recipes » Parsers and Interpreters     Intermediate License: The MIT License

C#/.NET Command Line Arguments Parser

By GriffonRL

Class to parse command line arguments and store/retrieve them.
C#, Windows, .NET1.0, Dev
Posted:27 Oct 2002
Updated:5 Nov 2002
Views:342,034
Bookmarked:180 times
printPrint Friendly   add Share
      Discuss Discuss   Broken Article?Report  
76 votes for this article.
Popularity: 8.94 Rating: 4.75 out of 5
2 votes, 3.0%
1
1 vote, 1.5%
2

3
7 votes, 10.6%
4
56 votes, 84.8%
5

Introduction

Even with modern UI, we often need a way to start our programs with specific parameters. Command line arguments are helpful to provide those parameters without exposing them to everybody. When developing with .NET and C# you can get the command line arguments from your Main(string[] Args) function. Args is in fact an array containing all the strings separated by spaces entered in the command line. What the following class does is to transform this array of strings into a ready to use collection of key/value pairs. You can then easily find and get from this collection a specific value for one of your parameters (key).

The Arguments class

This class parses your command line arguments, find all parameters starting with -, -- or / and all the values linked. I assumed that a value could be separated from a parameter with a space, a : or a =. The parser also look for enclosing characters like ' or " and remove them. Of course if you have a value like 'Mike's house', only the first and last ' will be removed. To achieve its goal, the class relies heavily on the regular expressions capabilities of .NET. The first regular expression (^-{1,2}|^/|=|:) splits one argument into several parts:

  • the parameter
  • the value

This regular expression handles cases where only a parameter is present, only a value is present or if both are present. The program performs accordingly to the number of parts found. The second regular expression (^['"]?(.*?)['"]?$) is used to detect and remove all starting and trailing ' or " characters from a value. When all your arguments are parsed, retrieving a value from a parameter is as easy as writing MyValue=params["MyParam"]. If the parameter doesn't exist or was not in the command line then you will get a null reference you can test against.

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

namespace CommandLine.Utility
{
    /// <summary>

    /// Arguments class

    /// </summary>

    public class Arguments{
        // Variables

        private StringDictionary Parameters;

        // Constructor

        public Arguments(string[] Args)
        {
            Parameters = new StringDictionary();
            Regex Spliter = new Regex(@"^-{1,2}|^/|=|:",
                RegexOptions.IgnoreCase|RegexOptions.Compiled);

            Regex Remover = new Regex(@"^['""]?(.*?)['""]?$",
                RegexOptions.IgnoreCase|RegexOptions.Compiled);

            string Parameter = null;
            string[] Parts;

            // Valid parameters forms:

            // {-,/,--}param{ ,=,:}((",')value(",'))

            // Examples: 

            // -param1 value1 --param2 /param3:"Test-:-work" 

            //   /param4=happy -param5 '--=nice=--'

            foreach(string Txt in Args)
            {
                // Look for new parameters (-,/ or --) and a

                // possible enclosed value (=,:)

                Parts = Spliter.Split(Txt,3);

                switch(Parts.Length){
                // Found a value (for the last parameter 

                // found (space separator))

                case 1:
                    if(Parameter != null)
                    {
                        if(!Parameters.ContainsKey(Parameter)) 
                        {
                            Parts[0] = 
                                Remover.Replace(Parts[0], "$1");

                            Parameters.Add(Parameter, Parts[0]);
                        }
                        Parameter=null;
                    }
                    // else Error: no parameter waiting for a value (skipped)

                    break;

                // Found just a parameter

                case 2:
                    // The last parameter is still waiting. 

                    // With no value, set it to true.

                    if(Parameter!=null)
                    {
                        if(!Parameters.ContainsKey(Parameter)) 
                            Parameters.Add(Parameter, "true");
                    }
                    Parameter=Parts[1];
                    break;

                // Parameter with enclosed value

                case 3:
                    // The last parameter is still waiting. 

                    // With no value, set it to true.

                    if(Parameter != null)
                    {
                        if(!Parameters.ContainsKey(Parameter)) 
                            Parameters.Add(Parameter, "true");
                    }

                    Parameter = Parts[1];

                    // Remove possible enclosing characters (",')

                    if(!Parameters.ContainsKey(Parameter))
                    {
                        Parts[2] = Remover.Replace(Parts[2], "$1");
                        Parameters.Add(Parameter, Parts[2]);
                    }

                    Parameter=null;
                    break;
                }
            }
            // In case a parameter is still waiting

            if(Parameter != null)
            {
                if(!Parameters.ContainsKey(Parameter)) 
                    Parameters.Add(Parameter, "true");
            }
        }

        // Retrieve a parameter value if it exists 

        // (overriding C# indexer property)

        public string this [string Param]
        {
            get
            {
                return(Parameters[Param]);
            }
        }
    }
}

The test class

Here is an example of how to use the Arguments class. As usual, the code is available in the zip file.

using System;
using CommandLine.Utility;

namespace CommandLine
{
    /// <summary>

    /// Testing class

    /// </summary>

    class Test
    {
        /// <summary>

        /// Main loop

        /// </summary>

        [STAThread]
        static void Main(string[] Args)
        {
        // Command line parsing

        Arguments CommandLine=new Arguments(Args);

        // Look for specific arguments values and display 

        // them if they exist (return null if they don't)

        if(CommandLine["param1"] != null) 
            Console.WriteLine("Param1 value: " + 
                CommandLine["param1"]);
        else
            Console.WriteLine("Param1 not defined !");

        if(CommandLine["height"] != null) 
            Console.WriteLine("Height value: " + 
                CommandLine["height"]);
        else 
            Console.WriteLine("Height not defined !");

        if(CommandLine["width"] != null) 
            Console.WriteLine("Width value: " + 
                CommandLine["width"]);
        else 
            Console.WriteLine("Width not defined !");

        if(CommandLine["size"] != null) 
            Console.WriteLine("Size value: " + 
                CommandLine["size"]);
        else 
            Console.WriteLine("Size not defined !");

        if(CommandLine["debug"] != null) 
            Console.WriteLine("Debug value: " + 
                CommandLine["debug"]);
        else 
            Console.WriteLine("Debug not defined !");

        // Wait for key

        Console.Out.WriteLine("Arguments parsed. Press a key");
        Console.Read();
        }
    }
}

Execution sample

I provided the following command line as the Arguments setting in the properties dialog of the Visual Studio .NET solution included in the ZIP file: -size=100 /height:'400' -param1 "Nice stuff !" --debug that command line produced the following output

Param1 value: Nice stuff !
Height value: 400
Width not defined !
Size value: 100
Debug value: true
Arguments parsed. Press a key...

Conclusion

In this article with saw how to parse, store and retrieve the arguments line of a .NET application. This class is versatile enough to handle a lot of different kind of arguments. Compatible with most of the forms we are used to (-param, --param or Windows /param). Thanks to the regular expressions for this. Using regular expressions allowed us to keep the Arguments class very small and the usage is very simple. Regular expressions are very powerful and can be used for most of your parsing needs (as far as speed is not the main concern).

Special thanks to: Benjamin, Guillaume and Sebastien for their support :o)

Happy Coding!!!

History

  • October 28, 2002 - v1.0 Initial release
  • November 6, 2002 - v1.1 Bug fix. Should be bug free now. Thanks to n2s for help.

License

This article, along with any associated source code and files, is licensed under The MIT License

About the Author

GriffonRL


Member
Richard Lopes Programmer originally from Paris, France.
I worked in France, the USA, New Caledonia and I'm now located in beautiful New Zealand and loving it.
Feel free to contact me for any business opportunity anywhere and in particular in New Zealand.

My blog: http://siliconz.com/blog My twitter: http://www.twitter.com/richard_lopes
Occupation: Software Developer (Senior)
Company: Sellla Ltd
Location: New Zealand New Zealand

Other popular Algorithms & Recipes articles:

Article Top
 
You must Sign In to use this message board.
FAQ FAQ 
 
Noise Tolerance  Layout  Per page   
 Msgs 1 to 25 of 108 (Total in Forum: 108) (Refresh)FirstPrevNext
Generalpath as arguments Pinmemberroman3001784:13 24 Feb '10  
GeneralRe: path as arguments PinmemberTomazaz1:10 16 Mar '10  
GeneralGreat Tool Pinmemberariight13:03 27 Oct '09  
GeneralMy updated version PinmemberJake Ginnivan20:07 26 Jul '09  
GeneralRe: My updated version PinmemberGriffonRL20:34 26 Jul '09  
GeneralInteresting mix of comments! Pinmemberhughd1:40 12 Jul '09  
GeneralWhy to submit buggy code? PinmemberTomazaz4:04 30 Jan '09  
GeneralThis dude stole your work and then copyrighted it? Pinmembermike.griffin@entityspaces.net9:35 8 Jan '09  
GeneralRe: This dude stole your work and then copyrighted it? Pinmembermike.griffin@entityspaces.net9:37 8 Jan '09  
GeneralRe: This dude stole your work and then copyrighted it? PinmemberGriffonRL9:53 8 Jan '09  
GeneralRe: This dude stole your work and then copyrighted it? PinmemberGriffonRL10:05 8 Jan '09  
GeneralRe: This dude stole your work and then copyrighted it? Pinmembermike.griffin@entityspaces.net10:53 8 Jan '09  
GeneralRe: This dude stole your work and then copyrighted it? PinmemberGriffonRL11:46 8 Jan '09  
GeneralWindows XP anomaly and fix PinmemberTodd Smith14:15 8 Oct '08  
GeneralNConsoler - another command line parsing library Pinmembertihobrazov7:54 8 Sep '08  
Generalwhat could be better Pinmemberteetrinker70036:32 26 Jun '08  
General;) [modified] PinmemberITMaiO22:44 15 May '08  
QuestionLicense Type Pinmemberbhargav_j13:19 25 Mar '08  
QuestionRe: License Type PinmemberPeter Kneale1:30 24 Aug '08  
AnswerRe: License Type PinmemberGriffonRL1:39 24 Aug '08  
GeneralCan you please update the code PinmemberJoeBob10111:20 27 Sep '07  
GeneralExcellent PinmemberLu Yixiang20:15 4 Jun '07  
GeneralGreat code bud. Pinmembermrsnipey18:09 3 Jun '07  
GeneralThanks for this code! Pinmemberpatiman4:47 21 May '07  
JokeHurray for the French PinmemberPinx5:03 11 Apr '07  

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

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

PermaLink | Privacy | Terms of Use
Last Updated: 5 Nov 2002
Editor: James T. Johnson
Copyright 2002 by GriffonRL
Everything else Copyright © CodeProject, 1999-2010
Web18 | Advertise on the Code Project