GetOpt style command line processing in C# with Mono.GetOptions

Being a longtime Perl programmer, I came to take the wonderful GetOpt::Long standard module for granted. Easily defining and parsing required and optional command-line parameters was as simple as defining an array of the parameters you expect and dumping them into a hash usable by the program.

So when I began writing command-line apps in C# 2.0, I was rather disappointed to discover how lacking that language is in processing command-line options in a usable way. After a futile Google search for a suitable replacement, I eventually stumbled upon the Mono.GetOptions library. (I use Visual Studio 2005, and not Mono, otherwise I probably would have come across this library sooner).

The result is something that is much more comfortable in C# than trying to store the passed options in some sort of array or hashtable. Instead, a custom class is defined to hold the options, which then uses Attributes and reflection to not only bind these parameters to the correct properties, but also to describe them in a sensible way to make usage-doc generation (the kind you see with --help) a snap.

Following is an example of how to use this library, taken from a similar post regarding this library. First, you need to import the necessary assemblies (adding references if necessary); this includes not only Mono.GetOptions but the required reflection assemblies as well:

using System;
using System.Reflection;
using Mono.GetOptions;

Then, in AssemblyInfo.cs, add some information about your assembly using Attributes. The stub code for this was probably already generated by Visual Studio when you created the project:


// Attributes visible in " --help"
[assembly: AssemblyTitle ("go.exe")]
[assembly: AssemblyVersion ("1.0.*")]
[assembly: AssemblyDescription ("Mono.GetOptions Sample Program")]
[assembly: AssemblyCopyright ("Public Domain")]

// This is text that goes after " [options]" in help output.
[assembly: Mono.UsageComplement ("")]

// Attributes visible in " -V"
[assembly: Mono.About("Insert About Text Here.")]
[assembly: Mono.Author ("Your name here")]

Next, create a class to store those options. The names of the properties in your class will be used as the names of the parameters from the command line; you must supply descriptions and “short” versions of these. Take note of the ParsingMode property, which allows you to specify which of the various command-parsing modes to use (GNU, Linux, Windows, or “Both” — not sure which “both” that one refers to!)


class SampleOptions : Options
{
    // Long option is the variable name ("--file"), short option is -f
    [Option ("Write report to FILE", 'f')]
    public string file;

    // Long option is the variable name ("--quiet"), short option is -q
    [Option ("don't print status messages to stdout", 'q')]
    public bool quiet;

    // Long option is as specified ("--use-int"), no short option
    [Option ("Sample int option", "use-int")]
    public int use_int;

    public SampleOptions ()
    {
        base.ParsingMode = OptionsParsingMode.Both;
    }
}

And finally, a test program to use the options class:


class TestApp
{
    public static void Main (string[] args)
    {
        SampleOptions options = new SampleOptions ();
        options.ProcessArgs (args);

        Console.WriteLine ("Specified Program Options:");
        Console.WriteLine ("\t           file: {0}", options.file);
        Console.WriteLine ("\t          quiet: {0}", options.quiet);
        Console.WriteLine ("\t        use_int: {0}", options.use_int);

        Console.WriteLine ("Remaining Program Options:");
        foreach (string s in options.RemainingArguments) {
            Console.WriteLine ("\t{0}", s);
        }
    }
}

Some sample output:

C:\> go.exe --help

go.exe  1.0.1573.25851 - Public Domain
Mono.GetOptions Sample Program
 
Usage: go [options]
Options:
  -f --file:PARAM                Write report to FILE
  -? --help                      Show this help list
  -q --quiet                     don't print status messages to stdout
     --usage                     Show usage syntax and exit
     --use-int:PARAM             Sample int option
     --verbosegetoptions         Show verbose parsing of options
  -V --version                   Display version and licensing information

C:\> go.exe --V

go.exe  1.0.1573.25851 - Public Domain
Mono.GetOptions Sample Program
 
Insert About Text Here.
 
Authors:
        Your name here
Specified Program Options:
                   file:
                  quiet: False
                use_int: 0
Remaining Program Options: