When you have defined the command line arguments, you can parse the command line to determine their values. There are two basic ways to do this, described below.
The easiest way to parse the arguments is using the static CommandLineParser.Parse<T>()
helper
methods. These methods take care of parsing the arguments, handling errors, and printing usage help
if necessary.
A basic usage sample for the CommandLineParser
class is as follows:
public static int Main()
{
var arguments = CommandLineParser.Parse<MyArguments>();
if (arguments == null)
{
return 1; // Or a suitable error code.
}
return RunApplication(arguments);
}
This overload takes the arguments from the Environment.GetCommandLineArgs()
method, so there is
no need to pass them manually (though you can if desired), and the default ParseOptions
.
If argument parsing is successful, the CommandLineParser
will create a new instance of the class
defining the arguments, passing the values parsed from the command line to the constructor
parameters (if any). It will then set the value of each property to the value of the corresponding
argument. This is not done in any particular order, so do not write code that makes assumptions
about this. Finally, it will return the instance.
Argument parsing can fail for a number of reason, including:
- Not all required arguments were specified.
- An argument name was supplied without a value for an argument that’s not a switch
- An unknown argument name was supplied
- A non-multi-value argument was specified more than once
- Too many positional argument values were supplied
- Argument value conversion failed for one of the arguments.
- An argument failed validation.
See the CommandLineArgumentErrorCategory
enumeration for more information. In addition, parsing
could have been canceled by an argument using the CommandLineArgumentAttribute.CancelParsing
property, a method argument, or the automatic -Help
and -Version
arguments.
If argument parsing does fail or was canceled, the static Parse<T>()
method
returns null. The method has already printed error and usage information, and there's nothing you
need to do except exit your application.
The static Parse<T>()
will not throw an exception, unless the arguments type
violates one of the rules for valid arguments (such as defining an optional positional argument
after a required one). An exception from this method typically indicates a mistake in your arguments
class.
You can customize various aspects of the parsing behavior using either the
ParseOptionsAttribute
, applied to your arguments class, or a ParseOptions
instance
passed to the Parse<T>()
method. The latter can be used to set a few options not
available with the ParseOptionsAttribute
, including options to customize the usage help and
error messages.
The ParseOptions
class can even be used to redirect where errors and help are written.
using var writer = LineWrappingTextWriter.ForStringWriter();
var options = new ParseOptions()
{
Error = writer,
Mode = ParsingMode.LongShort,
DuplicateArguments = ErrorMode.Warning,
UsageWriter = new UsageWriter(writer);
};
var arguments = CommandLineParser.Parse<MyArguments>(options);
if (arguments == null)
{
// There are probably better ways to show help in a GUI app than this.
MessageBox.Show(writer.ToString());
return 1;
}
In the vast majority of cases, ParseOptionsAttribute
and ParseOptions
should be sufficient to
customize the parsing behavior to your liking. If you need access to the CommandLineParser
instance
after parsing finished, you can use injection,
so it should rarely be necessary to use the manual parsing method.
If you wish to customize the error messages shown to the user if parsing fails, for example to
localize them, you can do that using the LocalizedStringProvider
class. This class is used as
the source for all error messages, as well as a number of other strings used by Ookii.CommandLine.
Create a class that derives from the LocalizedStringProvider
class and override its members to
customize any strings you wish to change. You can specify a custom string provider using the
ParseOptions.StringProvider
class.
Alternatively, if you need more error information, you can use the manual parsing method below, and
use the CommandLineArgumentException.Category
property to determine the cause of the exception
and create your own error message.
The static Parse<T>()
method and its overloads will likely be sufficient for most
use cases. However, sometimes you may want even more fine-grained control. This includes the ability
to handle the ArgumentParsed
and DuplicateArgument
events, and to get
additional information about the arguments using the Arguments
property or the
GetArgument
function.
In this case, you can manually create an instance of the CommandLineParser<T>
class. Then, call
the instance ParseWithErrorHandling()
or Parse()
method.
The
CommandLineParser<T>
class is a helper class that derives fromCommandLineParser
and provides strongly-typedParse()
andParseWithErrorHandling()
methods.
Using ParseWithErrorHandling()
is the easiest in this case, because it will still handle
printing error messages and usage help, the same as the static Parse<T>()
method. If you want
more information about the error that occurred, you can access the CommandLineParser.ParseResult
property after parsing.
For example, you can use this approach if you want to return a success status when parsing was canceled, but not when a parsing error occurred:
var parser = new CommandLineParser<MyArguments>();
var arguments = parser.ParseWithErrorHandling();
if (arguments == null)
{
return parser.ParseResult.Status == ParseStatus.Canceled ? 0 : 1;
}
You can also use the ParseResult.ArgumentName
property to determine which argument canceled
parsing in this case. If an error occurred, the status will be ParseStatus.Error
and you can use
the ParseResult.LastException
property to access the actual error that occurred.
For the most fine grained control, you can use the CommandLineParser<T>.Parse()
method, which
lets you handle errors manually.
If argument parsing fails, the instance CommandLineParser<T>.Parse()
method will throw a
CommandLineArgumentException
exception, which you need to handle. You can simply print the
exception message, or check the CommandLineArgumentException.Category
property to determine
the cause of the error.
The non-static Parse()
method returns null only if parsing was canceled. This also
happens if the automatic -Help
or -Version
arguments were used.
The automatic -Help
argument implementation doesn't actually show help; it relies on the caller to
do so. However, if the Parse()
method returns null, it does not necessarily mean
that you should display usage help. For example, the automatic -Version
argument cancels parsing,
but should typically not result in a help message.
To see whether you should show usage help, check the HelpRequested
property. This property
will always be true if an exception was thrown, and always be false if the
Parse()
method returned an instance.
If the Parse()
method returned null, you can also check the
CommandLineParser.ParseResult
property to see which argument canceled parsing.
Here is a basic sample of manual parsing and error handling using the Parse()
method:
static int Main()
{
var parser = new CommandLineParser<MyArguments>();
try
{
var arguments = parser.Parse();
if (arguments != null)
{
return RunApplication(arguments);
}
}
catch (CommandLineArgumentException ex)
{
Console.Error.WriteLine(ex.Message);
}
if (parser.HelpRequested)
{
parser.WriteUsage();
}
return 1;
}
If you wish to customize the behavior, that can still be done using the ParseOptionsAttribute
attribute and the ParseOptions
class (which you can pass to the CommandLineParser<T>
constructor). Some properties of the ParseOptions
class (like Error
) are not used with
the Parse()
methods, as they apply to the ParseWithErrorHandling()
and the static
Parse<T>()
methods only.
Next, we'll take a look at generating usage help.