Click here to Skip to main content
Click here to Skip to main content
Go to top

Advanced command line parser class for .NET

, 8 Sep 2010
Rate this:
Please Sign up or sign in to vote.
The article presents a flexible command line parser with support for both Windows and Unix style arguments format.

Introduction

While I was working on the docking framework DocktorUI library, I felt a part of the code, though useful in some cases, was really old and completely off the scope of the project and didn't fit quite right with the rest. So I decided to remove it, but again, because I considered it could be of use to some people, instead of throwing it away, it would have been better to make it available to those few people. The code was made of a set of C# classes used for a general application startup control. A few classes were aimed at IPC (inter-process communication) through the usage of Windows named pipes, plus another class which is instead dedicated to parsing Windows or Unix style command lines. I decided to only provide the latter, as Named Pipes are now handled by .NET 3.5, thus making my IPC code more or less obsolete.

Background

I know there are other options around offering similar functionality. I'm not pretending to assume this is any better or more complete, nor does it introduce anything new I guess. I haven't checked the others so I couldn't even tell. I already had this code, so I'm just making it public. Hopefully, it will be of use to somebody.

Using the code

The CommandLine class allows an application to have intricate command line parsing built-in. Keep in mind that this code hasn't really been used in production, so it could have a few flaws. The class is pretty straightforward to use, plus it's heavily commented.

CommandLine cmdLine = new CommandLine(args);
String arg = cmdLine["name"];

I think the code is pretty self-explanatory. You can instantiate the class with a list of parameters or a string containing the entire command line. The parsing is done in-line using grammatic analysis, similar to how a generated lexer would do it. This makes it easier to add/change functionality, at least in my opinion. There's also a draft of an equivalent grammar in the comments. Although this is just a guideline model, it hasn't actually been used to generate the parsing code. Here is the mentioned grammar:

/// Grammar
/// 
/// parameters : parameter*
///            ;
/// 
/// parameter : '/' parameter-struct
///           | '--' parameter-struct
///           | '-' parameter-struct
///           ;
/// 
/// parameter-struct : parameter-name (parameter-separator parameter-value)? ;
/// 
/// parameter-name : parameter-name-char+ ;
/// 
/// parameter-separator : ':'
///                     | '='
///                     | ' '
///                     ;
/// 
/// parameter-value : '\'' (ANY LESS '\'')* '\''
///                 | '"' (ANY LESS '"')* '"'
///                 | (parameter-value-first-char parameter-value-char*)?
///                 ;
/// 
/// parameter-name-char : ANY LESS ' ', ':', '=' ;
/// 
/// parameter-value-first-char : ANY LESS ' ', '/', ':', '=' ;
/// 
/// parameter-value-char : ANY LESS ' ' ;
/// 
/// 
/// Matches:
/// 
/// Application.exe /new /parm: "A parameter can be '/parm: 
///     '/value:''" /parm2: value2 /parm3: "value3: 'the value'"

Here's the complete demo application code that can probably make it even more clear on the features offered by the class:

using System;
using System.Collections.Generic;
using System.Text;
using StartUp;

namespace CommandLineDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            CommandLine cmdLine = new CommandLine(args);

            PrintCommandLine(cmdLine);

            Console.WriteLine("Insert Command Line to parse or Return to exit.");

            String cmd = Console.ReadLine();

            while (!String.IsNullOrEmpty(cmd))
            {
                cmdLine.ParametersString = cmd;

                PrintCommandLine(cmdLine);

                cmd = Console.ReadLine();
            }
        }

        static void PrintCommandLine(CommandLine cmdLine)
        {
            String cmd = cmdLine.ParametersString;
            IDictionary<String, String> args = cmdLine.Parameters;

            if (!String.IsNullOrEmpty(cmd))
            {
                if (cmdLine.Success)
                {
                    Console.WriteLine("Command Line parsed successfully. Result:");

                    foreach (String key in args.Keys)
                    {
                        Console.WriteLine("\"{0}\" => \"{1}\"", key, args[key]);
                    }
                }
                else
                {
                    Console.WriteLine("Error while parsing Command Line. " + 
                                      "Position marked with <---:");
                    int offset = cmdLine.ErrorOffset + 1;
                    Console.WriteLine("{0}<---{1}", 
                            cmd.Substring(0, offset), cmd.Substring(offset));
                }
            }
        }
    }
}

Conclusions

I'd like to conclude by repeating the sort-of disclaimer above: I know there's been already other solutions offering the same functionality. Mine doesn't necessarily add anything new or better. I just wanted to share this old code that I had. That being said, I hope you find it somehow useful or interesting.

License

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

Share

About the Author

Elia Sarti
Synved Ltd.
Ireland Ireland

Comments and Discussions

 
GeneralVery Nice PinmemberTL Wallace9-Sep-10 10:20 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    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 | Mobile
Web02 | 2.8.140916.1 | Last Updated 8 Sep 2010
Article Copyright 2010 by Elia Sarti
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid