Pregunta

Cuando la construcción de aplicaciones de consola que toman los parámetros, puede utilizar los argumentos que se pasan a Main(string[] args).

En el pasado, simplemente hemos indexado/bucle de la matriz y hace un par de expresiones regulares para extraer los valores.Sin embargo, cuando los comandos obtener más complicado, el análisis puede ser bastante feo.

Así que estoy interesado en:

  • Las bibliotecas de uso
  • Los patrones que utiliza

Asumir los comandos siempre se adhieren a los estándares comunes, tales como la respuesta aquí.

¿Fue útil?

Solución

Me gustaría sugerir fuertemente el uso de NDesk.Opciones (Documentación) y/o Mono.Opciones (la misma API, espacio de nombres diferente).Un ejemplo de la documentación:

bool show_help = false;
List<string> names = new List<string> ();
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<string> 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;
}

Otros consejos

Me gusta mucho la Línea de Comandos del Analizador de la Biblioteca ( http://commandline.codeplex.com/ ).Tiene una muy simple y elegante manera de configurar los parámetros a través de los 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();
    }
}

El WPF TestApi biblioteca viene con uno de los mejores de la línea de comandos analizadores para C# desarrollo.Recomiendo fijarse en él, de Ivo Manolov del blog en 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 todo el mundo tiene su propia mascota de la línea de comandos de los analizadores, la figura tenía mejor añadir la mía :).

http://bizark.codeplex.com/

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

A partir de la documentación...

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

  • Inicialización automática: Las propiedades de la clase se ajusta automáticamente basándose en los argumentos de línea de comandos.
  • Propiedades predeterminadas: Enviar un valor sin especificar el nombre de la propiedad.
  • Valor de conversión: Utiliza el potente ConvertEx clase también incluye en BizArk para convertir los valores para el tipo apropiado.
  • Boolean banderas: Los indicadores pueden ser especificados por la mera utilización del argumento (ex, /b para true y /b - para falso) o sumando el valor de verdadero/falso, sí/no, etc.
  • Argumento de matrices: Simplemente agregar varios valores después de que el nombre de línea de comandos para establecer una propiedad que se define como una matriz.Ex, /x 1 2 3 llenará de x con la matriz { 1, 2, 3 } (suponiendo que x se define como una matriz de enteros).
  • De la línea de comandos alias: Una propiedad puede soportar múltiples de la línea de comandos alias para él.Por ejemplo, Ayudar a que utiliza el alias ?.
  • Parcial nombre de reconocimiento: No es necesario escribir el nombre completo o apodo, solo hechizo suficiente para que el analizador para eliminar la ambigüedad de la propiedad/alias de los demás.
  • Soporta ClickOnce: Puede inicializar las propiedades, incluso cuando se especifica como la cadena de consulta en una dirección URL para ClickOnce las aplicaciones desplegadas.La línea de comandos de inicialización método de detectar si se está ejecutando como ClickOnce o no, por lo que su código no necesita cambiar cuando se utiliza.
  • Crea automáticamente /?ayuda: Esto incluye agradable formato que toma en cuenta el ancho de la consola.
  • Cargar/Guardar argumentos de línea de comandos a un archivo: Esto es especialmente útil si usted tiene varias de grandes y complejos conjuntos de argumentos de línea de comandos que desea ejecutar varias veces.

Escribí un C# argumento de línea de comandos analizador de hace un tiempo.En: http://www.codeplex.com/CommandLineArguments

CLAP (argumento de línea de comandos parser) tiene un utilizable API y es maravillosamente documentado.Realizar un método de anotación de los parámetros. https://github.com/adrianaisemberg/CLAP

Existen numerosas soluciones para este problema.Para la integridad y a proporcionar la alternativa si alguien deseos voy a agregar esta respuesta para las dos clases útiles en mi google code library.

La primera es ArgumentList que sólo es responsable de los análisis de parámetros de línea de comandos.Recoge pares de nombre-valor definido por interruptores '/x:y' o '-x=y' y también recopila una lista de 'sin nombre' entradas.Es básico el uso que se discute aquí, vista de la clase aquí.

La segunda parte de este es el CommandInterpreter lo que crea un totalmente funcional de la aplicación de línea de comandos de su .Clase Net.Como un 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 de arriba puede ejecutar el siguiente:

Program.exe Haceralgo "cadena de valor" 5

-- o --

Program.exe haceralgo /ivalue=5 -svalue:"cadena de valor"

Es así de simple o tan complejo como usted necesita que sea.Usted puede revisar el código fuente, ver la ayuda, o descargar el binario.

Me gusta que uno, porque se puede "definir" reglas para los argumentos, necesaria o no,...

o si usted es un tipo Unix, que puede que te guste la GNU Getopt .NET puerto.

Usted puede tener gusto de mi La alfombra.Cmd

Fácil de usar y ampliable argumento de línea de comandos analizador.Manijas:Bool, Más / Menos, cadena, Cadena de la Lista, CSV, Enumeración.

Construido en '/?' modo de ayuda.

Construido en '/??' y '/?D' documento generador de modos.

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 ser visto como un aval de parte de un tercero.Lo que me dijo de hacer uso de ella para cada línea de comandos de programa basado escribo, es de código abierto y es mi esperanza de que otros puedan beneficiarse de ella.

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

Puede analizar los argumentos usando
1.atributos
2.llamadas explícitas
3.sola línea de múltiples argumentos O matriz de cadena

Puede manejar cosas como la siguiente:

-config:Control de calidadstartdate:${hoy} -región:'Nueva York' Settings01

Es muy fácil de usar.

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

Este está dirigido a aplicaciones de consola que ejecutar un while (input !="exit") estilo de bucle, una consola interactiva, tales como FTP de la consola, 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:

/// <summary>
/// A class for parsing commands inside a tool. Based on Novell Options class (http://www.ndesk.org/Options).
/// </summary>
public class CommandOptions
{
    private Dictionary<string, Action<string[]>> _actions;
    private Dictionary<string, Action> _actionsNoParams;

    /// <summary>
    /// Initializes a new instance of the <see cref="CommandOptions"/> class.
    /// </summary>
    public CommandOptions()
    {
        _actions = new Dictionary<string, Action<string[]>>();
        _actionsNoParams = new Dictionary<string, Action>();
    }

    /// <summary>
    /// Adds a command option and an action to perform when the command is found.
    /// </summary>
    /// <param name="name">The name of the command.</param>
    /// <param name="action">An action delegate</param>
    /// <returns>The current CommandOptions instance.</returns>
    public CommandOptions Add(string name, Action action)
    {
        _actionsNoParams.Add(name, action);
        return this;
    }

    /// <summary>
    /// Adds a command option and an action (with parameter) to perform when the command is found.
    /// </summary>
    /// <param name="name">The name of the command.</param>
    /// <param name="action">An action delegate that has one parameter - string[] args.</param>
    /// <returns>The current CommandOptions instance.</returns>
    public CommandOptions Add(string name, Action<string[]> action)
    {
        _actions.Add(name, action);
        return this;
    }

    /// <summary>
    /// Parses the text command and calls any actions associated with the command.
    /// </summary>
    /// <param name="command">The text command, e.g "show databases"</param>
    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 Pedro 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 El FubuCore de la línea de Comandos de análisis de la aplicación que realmente me gusta, las razones son las siguientes:

  • es fácil de usar - aunque no he podido encontrar una documentación, la FubuCore solución también proporciona un proyecto que contenga un buen conjunto de Pruebas unitarias que hablar más acerca de la funcionalidad de cualquier documentación que podría
  • tiene un buen diseño orientado a objetos, no el código de repetición o de otras cosas que solía tener en mi línea de comandos de análisis de aplicaciones
  • es declarativa:básicamente escribir clases para los Comandos y los conjuntos de parámetros y los decoran con atributos para configurar varias opciones (por ejemplo,nombre, descripción, obligatorio/opcional)
  • la biblioteca, incluso imprime un bonito Gráfico de Uso, con base en estas definiciones

A continuación se muestra un sencillo ejemplo sobre cómo utilizar este.Para ilustrar el uso, he escrito una sencilla utilidad que tiene dos comandos:- agregar (agrega un objeto a una lista - un objeto se compone de un nombre(string), el valor(int) y un indicador booleano) - list (listas de todos los agregados actualmente objetos)

Primero de todo, me escribió una clase de Comando para la 'agregar' comando:

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

        return true;
    }
}

Este comando recibe un CommandInput instancia como parámetro, de modo que yo a definir la siguiente:

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 'la lista', 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<NullInput>
{
    public override bool Execute(NullInput input)
    {
        State.Objects.ForEach(Console.WriteLine);

        return false;
    }
}

La 'lista' de toma de comando sin parámetros, por lo que he definido un NullInput clase para este:

public class NullInput { }

Todo lo que queda ahora es de alambre de esto en el método Main (), como este:

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

        var executor = new CommandExecutor(factory);

        executor.Execute(args);
    }

El programa funciona como se esperaba, la impresión de consejos sobre el uso correcto en caso de que alguno de los comandos no son válidos:

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

Y un ejemplo de uso para el 'añadir' comando:

Usages for 'add' (Add object)
  add <objectname> [-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
  -------------------------------------

Commandlets Powershell.

El análisis hecho por powershell basado en los atributos especificados en la commandlets, apoyo para las validaciones, los conjuntos de parámetros, la canalización, los informes de error, ayuda, y lo mejor de todos los que regresan .NETO de objetos para su uso en otros commandlets.

Un par de enlaces que he encontrado útiles para comenzar:

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

Genghis Analizador De Línea De Comandos puede ser un poco fuera de fecha, pero es muy característica completa y funciona bastante bien para mí.

Yo sugeriría que la abrir-fuente de la biblioteca CSharpOptParse.Se analiza la línea de comandos y los hidratos de definido por el usuario .NET objeto con la entrada de línea de comandos.Siempre me dirijo a esta biblioteca al escribir una aplicación consola de C#.

Por favor, utilice el .puerto de red de la apache commons cli API.Esto funciona muy bien.

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

y el original de la API para los conceptos y la introducción

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

Una muy simple y de fácil uso ad hoc de la clase de línea de comandos de análisis, que apoya los 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<string, string>();
        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<string, string> 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"));
    }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top