.NET Command Line Options – Mono.GetOptions

I actually write .NET Command Line applications for Windows. I write little tools, that maybe would be usually be written in VBScript by a sysadmin, but since I was a sysadmin and AM a C# guy, I write in the latter. One thing that Microsoft seems to ignore (at least until PowerShell) is the command line and easy programming for the command line. I’ve never seen an equivalent to getopts in any MS Shell, or any API.

Mono implements a getopt library called Mono.GetOptions which works very nice on the Microsoft Platform as well. Just install Mono and copy the Mono.GetOptions.dll from C:\Program Files\Mono-1.2\lib\mono\2.0 or C:\Program Files\Mono-1.2\lib\mono\1.0 depending on which framework version you are targetting. I typically treat this dll as I do any third party dll as part of my project. In my case that means place in a lib directory and keep it under version control. I would prefer the Linux approach of no binaries under source control, but that doesn’t seem to be the standard on Windows projects.

Add the reference within your project to the lib/Mono.GetOptions.dll

The library works by extending Mono.GetOptions.Options and marking member with attributes.  The library includes many helpers, including the ability to automatically generate help messages.

class Options : Mono.GetOptions.Options {
  [Mono.GetOptions.Option(1,"Display this help message", 'h', "help")]
  public override Mono.GetOptions.WhatToDoNext DoHelp()
  {
    return base.DoHelp();
  }
}

The OptionAttribute has a number of default constructors.  In this case the arguments are maxOccurs, shortDescription, shortForm, longForm.  This allows the help to be displayed if you call Options.ProcessArgs with -h or -help.  See the source for more constructor forms: OptionAttribute.cs

To actually allow these options to be processed, you must call Options.ProcessArgs as I stated above.  You can play with options using this simple program:

    class Program
    {
        static void Main( string[] args )
        {
            Options lOptions = new Options();
            lOptions.ProcessArgs( args );

        }
    }

If you do this much and test by invoking with -h or -help, you will notice that there are some other options displayed in the output.  -help2 shows a couple of GetOptions debug and verbose options -~ and -. respectively.
  You will also see a message about using some assembly Attributes if you have not already added them.

[assembly: Mono.About( "This program does stuff." )]
[assembly: Mono.UsageComplement( "nonoptarg1 ... [nonoptargn]\nDo Stuff with nonoptarg1" )]
[assembly: Mono.Author( "Jay R. Wren" )]
[assembly: Mono.AdditionalInfo( "With no args this progam does stuff." )]
[assembly: Mono.ReportBugsTo( "jrwren@xmtp.net" )]

These assembly attributes work with the library to output usage information along with the normal System.Reflection.{AssemblyTitle,AssemblyCopyright,AssemblyDescription,AssemblyVersion} attributes.

Example:

Program 1.0.0.0 - Copyright c MyCorp - MyDiv 2006

Usage: Program [options] nonoptarg1 ... [nonoptargn]
DoStuff with nonoptarg1
Options:
  -h -help     Display this help message
     -help2    Show an additional help list
     -usage    Show usage syntax and exit
  -V -version  Display version and licensing information

With no flags, the current users known host putty registry keys will be listed.

Please report bugs to <jrwren@xmtp.net>

Depending on your application you can use Options members such as:


[Mono.GetOptions.Option("debug level",'d',null)]
public int DebugLevel = 4;
[Mono.GetOptions.Option("warning level",'w',null)]
public WhatToDoNext SetWarnngLevel(int warningLevel)
{
  this.WarningLevel=warningLevel;
  return WhatToDoNext.GoAhead;
}

And now you can simply access the Options.DebugLevel and Options.WarningLevel members. They will be set if the -d and/or the -w options were used on command invocation.

Further examples can be seen in the mcat sample from Mono subversion.