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: