Making Command Line Arguments Easier [Matt Ellis]

Before we get to the meat of this blog post, I want to take a moment to introduce myself.  My name is Matt Ellis and I’m working this summer as an intern on the Base Class Libraries team.  I’m really enjoying my time here, and it’s pretty amazing to be working on a team whose work affects so many developers around the world!


One feature we are considering adding to a future release on the .NET Framework is a library to help developers writing applications that use command line arguments.  We’d like to be able to provide a simple framework for parsing these arguments so our users don’t have to waste time writing boilerplate code that extracts and validates arguments from the string array passed into the main method, and can instead focus on solving the problem at hand.


            The Windows PowerShell team has developed some framework to solve this problem in their space.  One of the key concepts in PowerShell is the Cmdlet, which is a small .NET class run within PowerShell to perform a specific task.  Authors of Cmdlets simply declare, via attributes within their code, properties and fields that should be used as command line arguments. PowerShell takes care of filling in these fields and properties based on arguments that come in from the command line.  PowerShell makes sure the types of incoming arguments are valid, that all mandatory arguments are given values and can even print usage information for an application.  You can read more about PowerShell by downloading the Microsoft Windows SDK for Beta 2.  This is all really cool technology, but it requires PowerShell.  We’d like to be able to deliver a solution that would only require the .NET Framework.


            So we want to ask you, our customers, what features you’d like to see in a command line argument parser.  For example, is the ability to have order dependent parameters important, or should copy -A -V source.txt dest.txt work the same as copy -V -A source.txt dest.txt or copy source.txt dest.txt -A –V?  What about the ability to specify dependencies between arguments, such as –A can only appear if –B is also somewhere on the command line?  What features are most important to you when it comes to writing programs that take command line arguments?

Comments (12)

  1. A way to automatically generate the help page based on the command line arguments and descriptions would be nice.

  2. Keith Hill says:

    The PowerShell parameter/argument parsing is really good.  You can have both named parameters which can appear anywhere as well as unnamed arguments that get assigned to parameters based on attributes declaring the parameter’s position.  I also like their switch parameters as well as their ability to allow you to specify just enough of a parameter name to disambiguate it from the other parameter names.  Finally any additional parameters that don’t correspond to a declared parameter are available via $args (similar to Lisp Rest parameters).

    Just to round things out, you might want to take a look at the command line parser in Genghis.  It is also attribute based and is what we use for command line utilities.

  3. Tomer Gabel says:

    One feature that is often neglected in command line parsers is the ability to specify "debug-level" flags. Parameters that are flagged as debug-level should work exactly the same as other parameters, only they mustn’t show in the automatically-generated "Usage:" printout.

  4. David Banister says:

    What I think is most important is usability. In my opinion any logical way of specifying options should be acceptable. All of the following should do the same thing, but I that I lot of people would disagree with the last couple:

    thingy a b c

    thingy -a -b -c

    thingy /a /b /c

    thingy abc

    thingy a /b -c

    thingy /ab-c

  5. David Levine says:

    Some thoughts n addition to the above…

    1. Should be able to specify a response file that contains some or all the command line arguments; the parser should not care where the argument came from.  This will make it much easier to have tools automatically generate the argument list. For example… @list=<fileName>

    2. Default ordering should be order-independent. I can’t think of any use cases where I want the arguments to be order dependent, but if so, then it should be an option that must be explicitly enabled.

    3. Should be able to handle a number of different methods of specifying arugment data, such as /a=SomeValue or -a:aValue, or any number of other combinations.

    4. Getting the parser to handle quotes and embedded quotes is important.

    5. I prefer that the ability to specify argument dependencies and other validation be handled by the application after parsing is complete. If you want to build it in then I prefer that it use an extensible mechanism defined by the parser and implemented by the application. There are so many variables that it should be left to up to the application to determine whether or not the arguments are valid. A simple heuristic of "arg B can exist only if arg A exists" is unlikely to be of much value and is not very flexible.

    6. The parser should be able to generate the command line from input arguments; i.e. an Unparse method. This is useful for tools/batch files that invoke other tools.

    7. The generated command line must be capable of correctly round-tripping through the parser.

    8. Paths and embedded quotes must be handled correctly. e.g. if a string contains an embedded space then it should be surrounded by quote marks unless it already is surrounded by quotes.

    9. Should handle environment variables.

    Hope you enjoy your stay at MSFT.

  6. hmm… what i miss most? that there is no standard for getting the help about an commandline (/? /h /help -?,….). have no real problem about how i have to give it in, if i can read it somewhere. so really make an default implementation for an commandline tool, where you write your help text. e.g. with an dictionary where you add the param pattern and the explanation for that pattern and .net writes out the help on /? or whatever

  7. Jeremy Wiebe says:

    Just a few random comments:

    1. Re: David Levine’s comment #8.  I believe the Windows command prompt will properly handle paths with spaces, etc in them.  (Although the parser would have no way of telling what to do with this, for example:

    myapp.exe -f C:Document and Settingsmyuserfile.txt

    There’s probably some hueristics to "guess" where file.txt resides, but probably not 100% correct all the time.

    2. Having the ability to specify either long and/or short parameter variants would be nice.  

     For example:

     myapp.exe -f=test.txt

     … should be the same as…

     myapp.exe -file=test.txt

    Specifying both long and short parameter names should be optional (so that some parameters may only have a "short" variant and some only a "long" variant.)

    3. Case sensivity of parameter names should be supported (but optional).

  8. giovanni.costagliola says:

    Take a tour of getopt GNU library.

    Btw, it would be nice to have a short and long form for a swith.

    e.g.: -f <==> –file

    the possibility to imply a default set of values if a flag is used

    e.g. -x ==> -A -B

    the possibility to definy a "mandatory-set" of flags

    e.g. {-a, -b, -c}, I mean, if U use one of them you must use all the others

    and obviously a re or better a domain constraint on the possibile values

  9. giovanni.costagliola says:

    Take a tour of getopt GNU library.

    Btw, it would be nice to have a short and long form for a swith.

    e.g.: -f <==> –file

    the possibility to imply a default set of values if a flag is used

    e.g. -x ==> -A -B

    the possibility to definy a "mandatory-set" of flags

    e.g. {-a, -b, -c}, I mean, if U use one of them you must use all the others

    and obviously a re or better a domain constraint on the possibile values

  10. As one of the newest members of the BCL team, I wanted to take some time to introduce myself. I’m Matt

Skip to main content