views:

21

answers:

1

I am trying to utilize the OptionSet class in the following way:

  string resultsFileName = null;
  bool isHelp = false;

  var p = new OptionSet() {
    { "r=|resultsFile=",  "The file with the results", v => { resultsFileName = v; } }
    { "h|help", "Show this help", v => { isHelp = (v != null); } },
  };

  try
  {
    p.Parse(args);
  }
  catch (OptionException e)
  {
    Console.WriteLine("Invalid arguments: " + e.Message);
    ShowHelp(p);
    return;
  }

Thus, resultsFile option is expected to be required (according to documentation: http://www.ndesk.org/doc/ndesk-options/NDesk.Options/OptionValueType.html). However, when I run the program as is (i.e. with no command line arguments) the exception is not thrown. Please assist.

Update: It looks in debugger like when no command line options are provided, the private void AssertValid (int index) method will be never reached to throw new OptionException.

A: 

This is a duplicate of How to enforce required command-line options with NDesk.Options?, and the answer is the same: NDesk.Options doesn't support that.

Quoting myself:

As per the OptionValueType.Required docs, the = within an option specification doesn't apply to the OptionSet as a whole, but just to the value for that specific option.

The importance of this is really only relevant in two scenarios, so first let's consider the OptionSet parser:

string a = null;
string b = null;
var options = new OptionSet {
    { "a=", v => a = v },
    { "b=", v => b = v },
};

Scenario 1 where it's important is that OptionSet.Parse() works in a single-pass, forward-only manner, and does not look at option values to determine if they "should be" values. Thus, consider:

options.Parse(new[]{"-a", "-b"});

The result of this will be that a has the value "-b", and b is null. Since the handler for -a requires a value, it always gets the following value (unless the value is "encoded" into the original option, e.g. -a=value).

The second place where this is important is when a value-requiring option is the last option, and there isn't a value present for it:

options.Parse(new[]{"-a"});

This will throw an OptionException, as the handler for -a requires a value, and no value is present.

Consequently, if you have an option that itself is required (as opposed to an option that requires a value), you need to manually check for this:

string dir = null;
new OptionSet {
    { "o=", v => dir = v },
}.Parse (args);

if (dir == null)
    throw new InvalidOperationException ("Missing required option -o=DIR");
jonp
thanks for the fast answer! (a little pitty that this functionality is not supported, though, since it would contribute to robustness of the command-line arguments validation).
BreakPhreak