¿La mejor forma de analizar argumentos de línea de comando en C #?

Al crear aplicaciones de consola que toman parámetros, puede usar los argumentos pasados ​​a Main(string[] args) .

En el pasado simplemente he indexado / bucle esa matriz y he hecho algunas expresiones regulares para extraer los valores. Sin embargo, cuando los comandos se vuelven más complicados, el análisis puede ser bastante feo.

Entonces estoy interesado en:

  • Bibliotecas que usa
  • Patrones que usa

Asum que los comandos siempre se adhieren a los estándares comunes como los que se responden aquí .

Sugeriría usar NDesk.Options ( Documentation ) y / o Mono.Options (misma API, espacio de nombres diferente). Un ejemplo de la documentación :

 bool show_help = false; List names = new List (); int repeat = 1; var p = new OptionSet () { { "n|name=", "the {NAME} of someone to greet.", v => names.Add (v) }, { "r|repeat=", "the number of {TIMES} to repeat the greeting.\n" + "this must be an integer.", (int v) => repeat = v }, { "v", "increase debug message verbosity", v => { if (v != null) ++verbosity; } }, { "h|help", "show this message and exit", v => show_help = v != null }, }; List extra; try { extra = p.Parse (args); } catch (OptionException e) { Console.Write ("greet: "); Console.WriteLine (e.Message); Console.WriteLine ("Try `greet --help' for more information."); return; } 

Me gusta mucho la biblioteca de Command Line Parser ( http://commandline.codeplex.com/ ). Tiene una forma muy simple y elegante de configurar los parámetros a través de atributos:

 class Options { [Option("i", "input", Required = true, HelpText = "Input file to read.")] public string InputFile { get; set; } [Option(null, "length", HelpText = "The maximum number of bytes to process.")] public int MaximumLenght { get; set; } [Option("v", null, HelpText = "Print details during execution.")] public bool Verbose { get; set; } [HelpOption(HelpText = "Display this help screen.")] public string GetUsage() { var usage = new StringBuilder(); usage.AppendLine("Quickstart Application 1.0"); usage.AppendLine("Read user manual for usage instructions..."); return usage.ToString(); } } 

La biblioteca WPF TestApi viene con uno de los mejores analizadores de línea de comandos para el desarrollo de C #. Recomiendo consultarlo en el blog de Ivo Manolov sobre la API :

 // EXAMPLE #2: // Sample for parsing the following command-line: // Test.exe /verbose /runId=10 // This sample declares a class in which the strongly- // typed arguments are populated public class CommandLineArguments { bool? Verbose { get; set; } int? RunId { get; set; } } CommandLineArguments a = new CommandLineArguments(); CommandLineParser.ParseArguments(args, a); 

Parece que todos tienen sus propios analizadores de línea de comandos para mascotas, y es mejor que agregue los míos también :).

http://bizark.codeplex.com/

Esta biblioteca contiene un analizador de línea de comandos que inicializará una clase con los valores de la línea de comandos. Tiene un montón de características (lo he estado construyendo durante muchos años).

De la documentación …

El análisis de línea de comandos en el marco de BizArk tiene estas características clave:

  • Inicialización automática: las propiedades de clase se establecen automáticamente en función de los argumentos de la línea de comandos.
  • Propiedades predeterminadas: envíe un valor sin especificar el nombre de la propiedad.
  • Conversión de valor: utiliza la potente clase ConvertEx también incluida en BizArk para convertir valores al tipo correcto.
  • Indicadores booleanos: los indicadores se pueden especificar simplemente usando el argumento (por ejemplo, / b para verdadero y / b- para falso) o agregando el valor verdadero / falso, sí / no, etc.
  • Arreglos de argumentos: simplemente agregue varios valores después del nombre de la línea de comando para establecer una propiedad que se define como una matriz. Ex, / x 1 2 3 poblará x con la matriz {1, 2, 3} (suponiendo que x se define como una matriz de enteros).
  • Alias ​​de línea de comandos: una propiedad puede admitir múltiples alias de línea de comandos para él. Por ejemplo, ¿Ayuda usa el alias?
  • Reconocimiento parcial del nombre: no es necesario que deletree el nombre completo o el alias, solo deletree lo suficiente para que el analizador elimine la ambigüedad de la propiedad / alias de los demás.
  • Admite ClickOnce: puede inicializar propiedades incluso cuando se especifican como la cadena de consulta en una URL para aplicaciones implementadas ClickOnce. El método de inicialización de la línea de comandos detectará si se está ejecutando como ClickOnce o no, por lo que no es necesario que el código cambie al usarlo.
  • Crea automáticamente /? ayuda: Esto incluye un buen formato que tiene en cuenta el ancho de la consola.
  • Cargar / guardar argumentos de línea de comandos en un archivo: esto es especialmente útil si tiene múltiples conjuntos grandes y complejos de argumentos de línea de comandos que desea ejecutar varias veces.

Hace un tiempo escribí un analizador de argumentos de línea de comando C #. Está en: http://www.codeplex.com/CommandLineArguments

CLAP (analizador de argumentos de línea de comandos) tiene una API utilizable y está maravillosamente documentado. Haces un método, anotando los parámetros. https://github.com/adrianaisemberg/CLAP

Hay numerosas soluciones a este problema. Para completar y proporcionar la alternativa si alguien desea estoy agregando esta respuesta para dos clases útiles en mi biblioteca de códigos de google .

El primero es ArgumentList, que es el único responsable de analizar los parámetros de la línea de comando. Recoge pares de nombre-valor definidos por los modificadores ‘/ x: y’ o ‘-x = y’ y también recostack una lista de entradas ‘sin nombre’. Su uso básico se discute aquí , vea la clase aquí .

La segunda parte de esto es CommandInterpreter que crea una aplicación de línea de comandos completamente funcional fuera de su clase .Net. Como ejemplo:

 using CSharpTest.Net.Commands; static class Program { static void Main(string[] args) { new CommandInterpreter(new Commands()).Run(args); } //example 'Commands' class: class Commands { public int SomeValue { get; set; } public void DoSomething(string svalue, int ivalue) { ... } 

Con el código de ejemplo anterior, puede ejecutar lo siguiente:

Program.exe DoSomething “valor de cadena” 5

– o –

Program.exe dosomething / ivalue = 5 -svalue: “valor de cadena”

Es tan simple como eso o tan complejo como lo necesites. Puede revisar el código fuente , ver la ayuda o descargar el binario .

Me gusta eso , porque puedes “definir reglas” para los argumentos, necesarios o no, …

o si eres un chico de Unix, que te gustaría el puerto GNU Getopt .NET .

Puede que te guste mi Rug.Cmd

Analizador de argumentos de línea de comando fácil de usar y expandible. Controles: Bool, Plus / Minus, String, String List, CSV, Enumeration.

Construido en ‘/?’ modo de ayuda

Construido en ‘/ ??’ y modos de generador de documentos ‘/? D’.

 static void Main(string[] args) { // create the argument parser ArgumentParser parser = new ArgumentParser("ArgumentExample", "Example of argument parsing"); // create the argument for a string StringArgument StringArg = new StringArgument("String", "Example string argument", "This argument demonstrates string arguments"); // add the argument to the parser parser.Add("/", "String", StringArg); // parse arguemnts parser.Parse(args); // did the parser detect a /? argument if (parser.HelpMode == false) { // was the string argument defined if (StringArg.Defined == true) { // write its value RC.WriteLine("String argument was defined"); RC.WriteLine(StringArg.Value); } } } 

Editar: este es mi proyecto y, como tal, esta respuesta no debe verse como un respaldo de un tercero. Dicho esto, lo uso para cada progtwig basado en línea de comandos que escribo, es de código abierto y espero que otros se beneficien de él.

Hay un analizador de argumentos de línea de comandos en http://www.codeplex.com/commonlibrarynet

Puede analizar argumentos usando
1. atributos
2. llamadas explícitas
3. Sola línea de argumentos múltiples O conjunto de cadenas

Puede manejar cosas como las siguientes:

config : Qa – fecha de inicio : $ { today } – region : ‘Nueva York’ Configuraciones01

Es muy fácil de usar.

Este es un controlador que escribí basado en la clase Novell Options .

Este está dirigido a aplicaciones de consola que ejecutan un ciclo de estilo while while (input !="exit") , una consola interactiva como una consola FTP, por ejemplo.

Ejemplo de uso:

 static void Main(string[] args) { // Setup CommandHandler handler = new CommandHandler(); CommandOptions options = new CommandOptions(); // Add some commands. Use the v syntax for passing arguments options.Add("show", handler.Show) .Add("connect", v => handler.Connect(v)) .Add("dir", handler.Dir); // Read lines System.Console.Write(">"); string input = System.Console.ReadLine(); while (input != "quit" && input != "exit") { if (input == "cls" || input == "clear") { System.Console.Clear(); } else { if (!string.IsNullOrEmpty(input)) { if (options.Parse(input)) { System.Console.WriteLine(handler.OutputMessage); } else { System.Console.WriteLine("I didn't understand that command"); } } } System.Console.Write(">"); input = System.Console.ReadLine(); } } 

Y la fuente:

 ///  /// A class for parsing commands inside a tool. Based on Novell Options class (http://www.ndesk.org/Options). ///  public class CommandOptions { private Dictionary> _actions; private Dictionary _actionsNoParams; ///  /// Initializes a new instance of the  class. ///  public CommandOptions() { _actions = new Dictionary>(); _actionsNoParams = new Dictionary(); } ///  /// Adds a command option and an action to perform when the command is found. ///  /// The name of the command. /// An action delegate /// The current CommandOptions instance. public CommandOptions Add(string name, Action action) { _actionsNoParams.Add(name, action); return this; } ///  /// Adds a command option and an action (with parameter) to perform when the command is found. ///  /// The name of the command. /// An action delegate that has one parameter - string[] args. /// The current CommandOptions instance. public CommandOptions Add(string name, Action action) { _actions.Add(name, action); return this; } ///  /// Parses the text command and calls any actions associated with the command. ///  /// The text command, eg "show databases" public bool Parse(string command) { if (command.IndexOf(" ") == -1) { // No params foreach (string key in _actionsNoParams.Keys) { if (command == key) { _actionsNoParams[key].Invoke(); return true; } } } else { // Params foreach (string key in _actions.Keys) { if (command.StartsWith(key) && command.Length > key.Length) { string options = command.Substring(key.Length); options = options.Trim(); string[] parts = options.Split(' '); _actions[key].Invoke(parts); return true; } } } return false; } } 

Mi favorito personal es http://www.codeproject.com/KB/recipes/plossum_commandline.aspx por Peter Palotas:

 [CommandLineManager(ApplicationName="Hello World", Copyright="Copyright (c) Peter Palotas")] class Options { [CommandLineOption(Description="Displays this help text")] public bool Help = false; [CommandLineOption(Description = "Specifies the input file", MinOccurs=1)] public string Name { get { return mName; } set { if (String.IsNullOrEmpty(value)) throw new InvalidOptionValueException( "The name must not be empty", false); mName = value; } } private string mName; } 

Recientemente me encontré con la implementación de análisis de línea de comandos FubuCore Me gusta mucho, las razones son:

  • es fácil de usar, aunque no pude encontrar una documentación para él, la solución FubuCore también proporciona un proyecto que contiene un buen conjunto de pruebas unitarias que hablan más sobre la funcionalidad que cualquier otra documentación.
  • tiene un bonito diseño orientado a objetos, sin repetición de código u otras cosas que solía tener en mi línea de comandos para analizar aplicaciones
  • es declarativo: básicamente escribes clases para los comandos y conjuntos de parámetros y los decoras con atributos para establecer varias opciones (p. ej., nombre, descripción, obligatorio / opcional)
  • la biblioteca incluso imprime un gráfico de uso agradable, basado en estas definiciones

A continuación se muestra un ejemplo simple sobre cómo usar esto. Para ilustrar el uso, he escrito una utilidad simple que tiene dos comandos: – agregar (agrega un objeto a una lista – un objeto consta de un nombre (cadena), valor (int) y una bandera booleana) – lista (listas todos los objetos agregados actualmente)

Antes que nada, escribí una clase de comando para el comando ‘agregar’:

 [Usage("add", "Adds an object to the list")] [CommandDescription("Add object", Name = "add")] public class AddCommand : FubuCommand { public override bool Execute(CommandInput input) { State.Objects.Add(input); // add the new object to an in-memory collection return true; } } 

Este comando toma una instancia de CommandInput como parámetro, entonces lo defino a continuación:

 public class CommandInput { [RequiredUsage("add"), Description("The name of the object to add")] public string ObjectName { get; set; } [ValidUsage("add")] [Description("The value of the object to add")] public int ObjectValue { get; set; } [Description("Multiply the value by -1")] [ValidUsage("add")] [FlagAlias("nv")] public bool NegateValueFlag { get; set; } } 

El siguiente comando es ‘list’, que se implementa de la siguiente manera:

 [Usage("list", "List the objects we have so far")] [CommandDescription("List objects", Name = "list")] public class ListCommand : FubuCommand { public override bool Execute(NullInput input) { State.Objects.ForEach(Console.WriteLine); return false; } } 

El comando ‘list’ no toma parámetros, así que definí una clase NullInput para esto:

 public class NullInput { } 

Todo lo que queda ahora es conectar esto en el método Main (), así:

  static void Main(string[] args) { var factory = new CommandFactory(); factory.RegisterCommands(typeof(Program).Assembly); var executor = new CommandExecutor(factory); executor.Execute(args); } 

El progtwig funciona según lo esperado, imprimiendo sugerencias sobre el uso correcto en caso de que los comandos no sean válidos:

  ------------------------ Available commands: ------------------------ add -> Add object list -> List objects ------------------------ 

Y un uso de muestra para el comando ‘agregar’:

 Usages for 'add' (Add object) add  [-nv] ------------------------------------------------- Arguments ------------------------------------------------- objectname -> The name of the object to add objectvalue -> The value of the object to add ------------------------------------------------- ------------------------------------- Flags ------------------------------------- [-nv] -> Multiply the value by -1 ------------------------------------- 

Powershell Commandlets.

El análisis realizado por powershell se basa en los atributos especificados en los commandlets, es compatible con validaciones, conjuntos de parámetros, pipelining, informes de errores, ayuda y, lo mejor de todo, devuelve objetos .NET para su uso en otros commandlets.

Un par de enlaces me pareció útil para comenzar:

  • Tutorial de inicio rápido
  • Guía de progtwigción en MSDN
  • Referencia del espacio de nombres en MSDN

C # CLI es una biblioteca de análisis de argumentos de línea de comandos muy simple que escribí. Está bien documentado y es de código abierto.

Genghis Command Line Parser puede estar un poco desactualizado, pero está muy completo y funciona bastante bien para mí.

Sugeriría la biblioteca de código abierto CSharpOptParse . Analiza la línea de comando e hidrata un objeto .NET definido por el usuario con la entrada de la línea de comandos. Siempre me dirijo a esta biblioteca cuando escribo una aplicación de consola C #.

Utilice el puerto .net de la API cli de apache commons. Esto funciona genial

http://sourceforge.net/projects/dotnetcli/

y la API original para conceptos e introducción

http://commons.apache.org/cli/

Una clase ad hoc fácil de usar y muy simple para el análisis de línea de comandos, que admite argumentos predeterminados.

 class CommandLineArgs { public static CommandLineArgs I { get { return m_instance; } } public string argAsString( string argName ) { if (m_args.ContainsKey(argName)) { return m_args[argName]; } else return ""; } public long argAsLong(string argName) { if (m_args.ContainsKey(argName)) { return Convert.ToInt64(m_args[argName]); } else return 0; } public double argAsDouble(string argName) { if (m_args.ContainsKey(argName)) { return Convert.ToDouble(m_args[argName]); } else return 0; } public void parseArgs(string[] args, string defaultArgs ) { m_args = new Dictionary(); parseDefaults(defaultArgs ); foreach (string arg in args) { string[] words = arg.Split('='); m_args[words[0]] = words[1]; } } private void parseDefaults(string defaultArgs ) { if ( defaultArgs == "" ) return; string[] args = defaultArgs.Split(';'); foreach (string arg in args) { string[] words = arg.Split('='); m_args[words[0]] = words[1]; } } private Dictionary m_args = null; static readonly CommandLineArgs m_instance = new CommandLineArgs(); } class Program { static void Main(string[] args) { CommandLineArgs.I.parseArgs(args, "myStringArg=defaultVal;someLong=12"); Console.WriteLine("Arg myStringArg : '{0}' ", CommandLineArgs.I.argAsString("myStringArg")); Console.WriteLine("Arg someLong : '{0}' ", CommandLineArgs.I.argAsLong("someLong")); } }