424 lines
15 KiB
C#
424 lines
15 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Collections.Specialized;
|
|
|
|
using Yaulw.Tools;
|
|
|
|
namespace Yaulw.Other
|
|
{
|
|
/// <remarks>
|
|
/// CommandLine Arguments Parser for an Application
|
|
/// <example>
|
|
/// <code>
|
|
/// internal CMDline cmdline = new CMDline(typeof(App.CommandLine_Option), typeof(App.CommandLine_Flag));
|
|
///
|
|
/// public enum CommandLine_Flag
|
|
/// {
|
|
/// START,
|
|
/// STOP,
|
|
/// SHOW,
|
|
/// }
|
|
///
|
|
/// public enum CommandLine_Option
|
|
/// {
|
|
/// ADD_SOMETHING,
|
|
/// REMOVE_SOMETHING,
|
|
/// }
|
|
///
|
|
/// cmdline.Parse(e.Args);
|
|
///
|
|
/// if (cmdline.HasParams)
|
|
/// {
|
|
/// if (App.cmdline.ShowHelp || !App.cmdline.ParamsValid)
|
|
/// {
|
|
/// ShowCommandLineHelp();
|
|
/// return;
|
|
/// }
|
|
///
|
|
/// string AddSomething = cmdline.GetOptionValue<string>(CommandLine_Option.ADD_SOMETHING, ""); //</string>
|
|
/// }
|
|
/// </code>
|
|
/// </example>
|
|
/// </remarks>
|
|
public class CMDline
|
|
{
|
|
#region private Variables
|
|
|
|
// Flag or Option Specifiers CONSTS
|
|
private const String FLAG_OR_OPTION_SPECIFIER = "-/";
|
|
private const String HELP_FLAG_SPECIFIER = "?";
|
|
|
|
// Private Parsing Enums
|
|
private Type _CMDLineOptions = null;
|
|
private Type _CMDLineFlags = null;
|
|
|
|
// Private Parsing Data Structures
|
|
private Stack<String> _stringStack = new Stack<String>();
|
|
private StringDictionary _stringDictionary = new StringDictionary();
|
|
|
|
// Keep track of the last parsed args as an array
|
|
private string[] _lastparsedArgs = null;
|
|
|
|
#endregion
|
|
|
|
#region Construction
|
|
|
|
/// <summary>
|
|
/// The Command Line Class needs to know what Options and Flags to Parse for
|
|
/// </summary>
|
|
/// <param name="CMDLineOptions">Pass an Enum used to determine CommandLine Options</param>
|
|
/// <param name="CMDLineFlags">Pass an Enum used to determine CommandLine Flags</param>
|
|
public CMDline(Type Enum_CMDLineOptions, Type Enum_CMDLineFlags)
|
|
{
|
|
if (Enum_CMDLineOptions.IsEnum && Enum_CMDLineFlags.IsEnum)
|
|
{
|
|
_CMDLineOptions = Enum_CMDLineOptions;
|
|
_CMDLineFlags = Enum_CMDLineFlags;
|
|
}
|
|
else
|
|
throw new ArgumentException("Both CMDLineOptions and CMDLineFlags must be Enums");
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Public Properties
|
|
|
|
/// <summary>
|
|
/// True if User Passed in any Parameters
|
|
/// </summary>
|
|
public bool HasParams { get { return (_stringDictionary.Count >= 1); } }
|
|
|
|
/// <summary>
|
|
/// True if User requested Command-Line Help
|
|
/// </summary>
|
|
public bool ShowHelp { get { return GetFlagOrOptionValueBool(HELP_FLAG_SPECIFIER); } }
|
|
|
|
/// <summary>
|
|
/// True if all Parameters parsed are valid, False otherwise
|
|
/// </summary>
|
|
public bool ParamsValid
|
|
{
|
|
get
|
|
{
|
|
if (!HasParams)
|
|
return true;
|
|
|
|
string[] OptionNames = Enum.GetNames(_CMDLineOptions);
|
|
string[] FlagNames = Enum.GetNames(_CMDLineFlags);
|
|
|
|
// Get All Flags and Options
|
|
List<String> AllFlagsAndOptions = new List<String>();
|
|
foreach (string Option in OptionNames)
|
|
AllFlagsAndOptions.Add(Option.ToLower());
|
|
foreach (string Flag in FlagNames)
|
|
AllFlagsAndOptions.Add(Flag.ToLower());
|
|
|
|
// Verify the Parameters
|
|
bool InvalidParamFound = false;
|
|
foreach (string key in _stringDictionary.Keys)
|
|
{
|
|
InvalidParamFound = (key != HELP_FLAG_SPECIFIER) && !AllFlagsAndOptions.Contains(key);
|
|
if (InvalidParamFound)
|
|
break;
|
|
}
|
|
return !InvalidParamFound;
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Public Methods
|
|
|
|
/// <summary>
|
|
/// Main Entry Function to Retrieve an Option Value
|
|
/// </summary>
|
|
/// <typeparam name="T">Should be a System Type like string, bool, int32, double, decimal, etc...</typeparam>
|
|
/// <param name="option">option to retrieve (From CMDLineOptions Enum)</param>
|
|
/// <param name="DefaultValue">Default value to use if nothing was retrieved * Error occured *</param>
|
|
/// <returns>value or default value, if not found</returns>
|
|
public T GetOptionValue<T>(Enum option, T DefaultValue)
|
|
{
|
|
T RetVal = DefaultValue;
|
|
string StringVal = GetFlagOrOptionValueStr(option.ToString());
|
|
try
|
|
{
|
|
if (ObjTool.IsNotNullAndNotEmpty(StringVal))
|
|
{
|
|
RetVal = ObjTool.ConvertStringToObj<T>(StringVal);
|
|
}
|
|
}
|
|
catch (Exception) { /* ignore */ }
|
|
return RetVal;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Main Entry Function to Retrieve a Flag Value
|
|
/// </summary>
|
|
/// <param name="flag">flag enum to retrieve (From CMDLineFlags Enum)</param>
|
|
/// <returns>Bool Value found or false if not found</returns>
|
|
public bool GetFlagValue(Enum flag)
|
|
{
|
|
return GetFlagOrOptionValueBool(flag.ToString());
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns the Last Parsed Arguments as a string
|
|
/// </summary>
|
|
/// <returns>returns last parsed args or String.Empty if none</returns>
|
|
public string ParsedArgs()
|
|
{
|
|
if (_lastparsedArgs != null && _lastparsedArgs.Length > 0)
|
|
{
|
|
StringBuilder sb = new StringBuilder();
|
|
foreach (string s in _lastparsedArgs)
|
|
{
|
|
sb.Append(s);
|
|
sb.Append(" ");
|
|
}
|
|
|
|
sb.Remove(sb.Length - 1, 1); // remove trailing " "
|
|
return sb.ToString();
|
|
}
|
|
|
|
return string.Empty;
|
|
}
|
|
#endregion
|
|
|
|
#region Private Helper Functions
|
|
|
|
/// <summary>
|
|
/// Main Function used to Retrieve a String Value
|
|
/// </summary>
|
|
/// <param name="FlagOrOption">Flag or Option to get Value for</param>
|
|
/// <returns>Value or Empty if not found</returns>
|
|
private string GetFlagOrOptionValueStr(string FlagOrOption)
|
|
{
|
|
// If there is a FLAG_OR_OPTION_CHARS, stripe it
|
|
if (IsFlagOrOption(FlagOrOption))
|
|
FlagOrOption = GetFlagOrOption(FlagOrOption);
|
|
|
|
FlagOrOption = FlagOrOption.ToLower();
|
|
if (_stringDictionary.ContainsKey(FlagOrOption))
|
|
return _stringDictionary[FlagOrOption];
|
|
return String.Empty;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Main Function used to Retrieve a Bool Value
|
|
/// </summary>
|
|
/// <param name="FlagOrOption">Flag or Option to get Value for</param>
|
|
/// <returns>True or False if not found</returns>
|
|
private bool GetFlagOrOptionValueBool(string FlagOrOption)
|
|
{
|
|
try
|
|
{
|
|
string Value = GetFlagOrOptionValueStr(FlagOrOption);
|
|
if (!String.IsNullOrEmpty(Value))
|
|
{
|
|
bool bValue = bool.Parse(Value);
|
|
return bValue;
|
|
}
|
|
}
|
|
catch (Exception) { /*Ignore*/ }
|
|
return false;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Parsing Methods
|
|
|
|
/// <returns>true if the param is a flag or option</returns>
|
|
private bool IsFlagOrOption(string arg)
|
|
{
|
|
return (FLAG_OR_OPTION_SPECIFIER.Contains(arg[0].ToString()));
|
|
}
|
|
|
|
/// <returns>the Value of a Param</returns>
|
|
private string GetFlagOrOption(string arg)
|
|
{
|
|
return arg.Substring(1);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Main Entry Function used to Parse CommandLine parameters
|
|
/// </summary>
|
|
/// <param name="args">command line arguments</param>
|
|
/// <returns>true if any parsing occured, false otherwise</returns>
|
|
public bool Parse(string[] args)
|
|
{
|
|
return Parse(args, true);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Main Entry Function used to Parse CommandLine parameters
|
|
/// </summary>
|
|
/// <param name="args">command line arguments</param>
|
|
/// <param name="bAlwaysParseOptionsAsTrue">Allows you to not parse Options as True, if in case the option is blank it will just be considered a blank option/flag</param>
|
|
/// <returns>true if any parsing occured, false otherwise</returns>
|
|
public bool Parse(string[] args, bool bAlwaysParseOptionsAsTrue)
|
|
{
|
|
if (args == null || args.Length <= 0)
|
|
return false;
|
|
|
|
_stringDictionary.Clear();
|
|
_stringStack.Clear();
|
|
_lastparsedArgs = args;
|
|
foreach (string arg in args)
|
|
{
|
|
if (!String.IsNullOrEmpty(arg))
|
|
{
|
|
if (IsFlagOrOption(arg))
|
|
{
|
|
_stringStack.Push(GetFlagOrOption(arg).ToLower());
|
|
if (bAlwaysParseOptionsAsTrue)
|
|
_stringDictionary[GetFlagOrOption(arg).ToLower()] = "TRUE";
|
|
}
|
|
else
|
|
{
|
|
// must have a flag or option on the stack,
|
|
// if it does we use it
|
|
if (_stringStack.Count >= 1)
|
|
{
|
|
_stringDictionary[_stringStack.Pop()] = Parse_ArgCleanup(arg);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
_stringStack.Clear();
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Used only when cmd is constructed with (null, null),
|
|
/// and the cmd.Parse function is called. will iterate thru the internal
|
|
/// dictionary and stack and make sure that the command string / line items
|
|
/// are valid
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public string MakeValidCmdStrFromNewlyParsedCmdLine()
|
|
{
|
|
StringBuilder sb = new StringBuilder();
|
|
foreach (string key in _stringDictionary.Keys)
|
|
{
|
|
sb.Append(FLAG_OR_OPTION_SPECIFIER[0]);
|
|
sb.Append(MakeValidCmdStr(key));
|
|
sb.Append("=");
|
|
sb.Append(_stringDictionary[key]);
|
|
sb.Append("");
|
|
}
|
|
|
|
foreach (string flag in _stringStack)
|
|
{
|
|
sb.Append(FLAG_OR_OPTION_SPECIFIER[0]);
|
|
sb.Append(MakeValidCmdStr(flag));
|
|
sb.Append("");
|
|
}
|
|
|
|
// remove trailing space
|
|
sb = sb.Remove(sb.Length - 1, 1);
|
|
return sb.ToString();
|
|
}
|
|
|
|
/// <summary>
|
|
/// It appears that the Command-Line can foul us up sometimes when passing
|
|
/// certain arguments. This function deals with these special cases.
|
|
/// </summary>
|
|
/// <param name="arg">arg to check/poss.clean up</param>
|
|
/// <returns>cleaned up arg, if needed</returns>
|
|
private string Parse_ArgCleanup(string arg)
|
|
{
|
|
if (!String.IsNullOrEmpty(arg) &&
|
|
(arg.Length > 2) &&
|
|
(arg[arg.Length - 1] == '"')) // when passing a \ at the end of the command-line with a "
|
|
{
|
|
arg = arg.Remove(arg.Length - 1);
|
|
arg += "\\";
|
|
}
|
|
return arg;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Static Generate CmdLine Method
|
|
|
|
/// <summary>
|
|
/// Generates a CommandLine Parameter String from the Options/Flags Given
|
|
/// </summary>
|
|
/// <param name="Options">StringDictionary that contains all the Options, to use</param>
|
|
/// <param name="Flags">List that contains all the Flags to use</param>
|
|
/// <returns>a string that can be passed via the commandLine</returns>
|
|
public static string GenerateCmdLine(StringDictionary Options, List<String> Flags)
|
|
{
|
|
string CmdLine = String.Empty;
|
|
|
|
// Iterate Options, and add them
|
|
if (Options != null && Options.Count > 0)
|
|
{
|
|
foreach (string Key in Options.Keys)
|
|
{
|
|
string cmdKey = MakeValidCmdStr(Key);
|
|
string cmdValue = Options[Key];
|
|
CmdLine = CmdLine + FLAG_OR_OPTION_SPECIFIER[0] + cmdKey + " " + "\"" + cmdValue + "\"" + " ";
|
|
}
|
|
}
|
|
|
|
// Iterate Flags, and add them
|
|
if (Flags != null && Flags.Count > 0)
|
|
{
|
|
foreach (string Flag in Flags)
|
|
{
|
|
string cmdFlag = MakeValidCmdStr(Flag);
|
|
CmdLine = CmdLine + FLAG_OR_OPTION_SPECIFIER[0] + cmdFlag + " ";
|
|
}
|
|
}
|
|
|
|
// Return the generated Commmand Line
|
|
return CmdLine;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Ensures Integrity with the Generated CMDLine string that Keys don't
|
|
/// contain Illegal Characters
|
|
/// </summary>
|
|
/// <param name="Key">a Key to make sure it is valid</param>
|
|
/// <returns>a valid Key</returns>
|
|
private static string MakeValidCmdStr(string Key)
|
|
{
|
|
if (!String.IsNullOrEmpty(Key))
|
|
{
|
|
//":\\ _!@#$%^&()-+{}[],.;`~";
|
|
Key = Key.Replace(" ", "_");
|
|
Key = Key.Replace(":", "_");
|
|
Key = Key.Replace("\\", "_");
|
|
Key = Key.Replace("/", "_");
|
|
Key = Key.Replace("!", "_");
|
|
Key = Key.Replace("@", "_");
|
|
Key = Key.Replace("#", "_");
|
|
Key = Key.Replace("$", "_");
|
|
Key = Key.Replace("%", "_");
|
|
Key = Key.Replace("^", "_");
|
|
Key = Key.Replace("&", "_");
|
|
Key = Key.Replace("(", "_");
|
|
Key = Key.Replace(")", "_");
|
|
Key = Key.Replace("-", "_");
|
|
Key = Key.Replace("+", "_");
|
|
Key = Key.Replace("{", "_");
|
|
Key = Key.Replace("}", "_");
|
|
Key = Key.Replace("[", "_");
|
|
Key = Key.Replace("]", "_");
|
|
Key = Key.Replace(",", "_");
|
|
Key = Key.Replace(".", "_");
|
|
Key = Key.Replace(";", "_");
|
|
Key = Key.Replace("'", "_");
|
|
Key = Key.Replace("~", "_");
|
|
return Key;
|
|
}
|
|
return String.Empty;
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|