A special command line parser class that automatically parses command lines specified in a particular way
// Parse command line arguments in the form
// /xxx
// -xxx
// OR
// /xxx:yyy
// -xxx:yyy
// where xxx is a parameter name and yyy, when present, is a value to associate with it
// The actual command line argument is case insensitive (but not the value)
// so /username:Bob is the same as /USERNAME:Bob
public class CommandLineParser
{
readonly Dictionary<string, string> arguments = new Dictionary<string, string>();
public void ParseCommandLineArguments(
params string[] args )
{
const int NOTFOUND = -1;
//string[] args = Environment.GetCommandLineArgs();
Debug.WriteLine( "Args:" + string.Join( ",", args ) );
int ix = 0;
foreach ( string arg in args )
{
Debug.WriteLine( "arg[" + ix++.ToString() + "]=\'" + arg + "\'" );
}
foreach ( string rawArg in args )
{
// Get rid of whitespace chars at the beginning and end
string arg = rawArg.Trim();
bool argFound = ( arg.Length >= 2 ) && ( arg[ 0 ] == '/' || arg[ 0 ] == '-' );
if ( !argFound )
continue;
string argument = arg.Substring( 1 );
int end = argument.IndexOf( ':' );
string paramName = ( end > -1 ) ? argument.Substring( 0, end ) : argument;
if ( ( end == NOTFOUND ) && ( paramName.Length > 0 ) )
{
arguments.Add( paramName.ToUpperInvariant(), "" );
}
else
{
string value = argument.Substring( end + 1 );
arguments.Add( paramName.ToUpperInvariant(), value );
}
}
Debug.WriteLine( "Processed command line args:" );
foreach ( string argName in arguments.Keys )
{
Debug.WriteLine( argName + " = " + arguments[ argName ] );
}
}
public bool GetArgument(
string arg,
out string value )
{
value = "";
return arguments.TryGetValue( arg.ToUpperInvariant(), out value );
}
// eg '/u' could select the argument /username:Jim as long as no other arguments starts with 'u'
public bool GetUniqueArgumentStartingWith(
string startsWith,
out string value )
{
value = "";
bool res = string.IsNullOrEmpty( startsWith.Trim() );
if ( !res )
{
var keys = arguments.Keys.Where( ky => ky.StartsWith( startsWith.ToUpperInvariant() ) ).ToList();
res = ( keys.Count == 1 );
if ( res )
{
res = arguments.TryGetValue( keys[ 0 ], out value );
}
}
return res;
}
public bool HasUniqueArgumentStartingWith(
string startsWith )
{
bool res = !string.IsNullOrEmpty( startsWith.Trim() );
if ( res )
{
var keys = arguments.Keys.Where( ky => ky.StartsWith( startsWith.ToUpperInvariant() ) );
res = ( keys.Count() == 1 );
}
return res;
}
public bool HasArgument(
string arg )
{
return arguments.ContainsKey( arg.ToUpperInvariant() );
}
public IEnumerable<KeyValuePair<string, string>> Arguments()
{
foreach ( var entry in arguments )
{
yield return entry;
}
}
}
Unit testss that accomapny and demonstrate the use of the class:
[ TestFixture ]
public class CommandLineParserUnitTests
{
[ Test ]
public void SeveralValidArgsTest()
{
CommandLineParser clp = new CommandLineParser();
clp.ParseCommandLineArguments( "/user:John", "-password:All0aJadgar", "-IncludeMetaData" );
Assert.That( clp.HasArgument( "IncludeMetaData" ) );
string value;
bool res = clp.GetArgument( "user", out value );
Assert.IsTrue( res );
Assert.That( value == "John" );
res = clp.GetArgument( "smugering", out value );
Assert.IsFalse( res );
}
[ Test ]
public void EmptyArgAndValueTest()
{
CommandLineParser clp = new CommandLineParser();
clp.ParseCommandLineArguments( "/:" );
Assert.That( !clp.HasArgument( ":" ) );
}
[ Test ]
public void NoValueSpecifiedTest()
{
CommandLineParser clp = new CommandLineParser();
clp.ParseCommandLineArguments( "/dufftest:" );
string value;
Assert.That( clp.GetArgument( "dufftest", out value ) );
Assert.That( value.Length == 0 );
Assert.That( clp.HasArgument( "dufftest" ) );
}
}