Pergunta

Ao construir aplicativos de console que usam parâmetros, você pode usar os argumentos passados ??para Main(string[] args).

No passado eu simplesmente indexados / loop essa matriz e feito algumas expressões regulares para extrair os valores. No entanto, quando os comandos ficam mais complicadas, a análise pode ficar muito feio.

Então, eu estou interessado em:

  • As bibliotecas que você usa
  • Patterns que você use

Suponha que os comandos sempre aderir aos padrões comuns, como respondeu aqui .

Foi útil?

Solução

Gostaria de sugerir usando NDesk.Options ( Documentação ) e / ou Mono.Options (mesma API, namespace diferente). Um exemplo da documentação :

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;
}

Outras dicas

Eu realmente gosto da Linha Analisador Biblioteca Command ( http://commandline.codeplex.com/ ). Ele tem uma maneira muito simples e elegante da criação de parâmetros via 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();
    }
}

O biblioteca WPF TestAPI vem com uma das mais bonitas analisadores de linha de comando para C desenvolvimento #. Eu recomendo a olhar para ele, do blog Ivo de Manolov na 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);

Looks como todo mundo tem seus próprios analisadores pet de linha de comando, figura melhor eu adicionar minha também:).

http://bizark.codeplex.com/

Esta biblioteca contém uma href="http://bizark.codeplex.com/wikipage?title=Command-line%20Parsing&referringTitle=Home" rel="noreferrer"> analisador de linha de comando que a vontade inicializar uma classe com os valores da linha de comando. Ele tem uma tonelada de recursos (eu tenho construí-la ao longo de muitos anos).

A partir do href="http://bizark.codeplex.com/wikipage?title=Command-line%20Parsing&referringTitle=Home" documentação ...

de linha de comando de análise no âmbito BizArk tem estas características-chave:

  • inicialização automática:. Propriedades de classe são definidas automaticamente com base nos argumentos de linha de comando
  • Propriedades padrão:. Enviar em um valor sem especificar o nome da propriedade
  • Valor de conversão:. Usa a poderosa classe CONVERTEX também incluído no BizArk para converter valores para o tipo adequado
  • bandeiras booleanas: Flags pode ser especificado simplesmente usando o argumento (ex, / b para o verdadeiro e / b- para false) ou adicionando o valor verdadeiro / falso, sim / não, etc .
  • Argumento matrizes: Basta adicionar vários valores após o nome de linha de comando para definir uma propriedade que é definida como uma matriz. Ex, / x 1 2 3 irá preencher x com a matriz {1, 2, 3} (assumindo que x é definido como uma matriz de números inteiros).
  • comando de linha de aliases: A propriedade pode suportar vários aliases de linha de comando para ele. Por exemplo, Help usa o pseudônimo?.
  • Parcial reconhecimento do nome:. Você não precisa para soletrar o nome completo ou o alias, apenas soletrar o suficiente para o analisador para disambiguate a propriedade / alias os outros
  • Supports ClickOnce: é possível inicializar propriedades, mesmo quando eles são especificados como a string de consulta em um URL para ClickOnce implantado aplicações. O método de inicialização de linha de comando irá detectar se ele está sendo executado como ClickOnce ou não para que o seu código não precisa mudar quando usá-lo.
  • cria automaticamente /? ajuda:. Isto inclui formatação agradável que leva em conta a largura do console
  • Load / Save argumentos de linha de comando em um arquivo:. Isto é especialmente útil se você tiver vários conjuntos grandes e complexos de argumentos de linha de comando que você deseja executar várias vezes

Eu escrevi um argumento C # linha de comando analisador um tempo atrás. Seu em: http://www.codeplex.com/CommandLineArguments

CLAP (linha de comando analisador argumento) tem uma API utilizável e é maravilhosamente documentado. Você faz um método, anotando os parâmetros. https://github.com/adrianaisemberg/CLAP

Existem inúmeras soluções para este problema. Para completar e fornecer a alternativa se alguém deseja estou adicionando esta resposta para duas classes úteis em meu Google code biblioteca .

O primeiro é ArgumentList que é responsável apenas pela análise de parâmetros de linha de comando. Ele recolhe pares nome-valor definido pelo interruptores '/ x: y' ou '-X = Y' e também recolhe uma lista de entradas de '' não identificadas. É básico uso é discutido aqui , ver a classe aqui .

A segunda parte desta é o CommandInterpreter que cria uma aplicação de linha de comando totalmente funcional fora de sua classe .Net. Como um exemplo:

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)
        { ... }

Com o código de exemplo acima, você pode executar o seguinte:

Program.exe DoSomething "valor da cadeia" 5

- ou -

Program.exe dosomething / iValue = 5 -svalue: "valor da cadeia"

É tão simples como isso ou tão complexo como você precisa que ele seja. Você pode rever o código-fonte, ver o ajuda, ou baixar o binário.

Gosto que um , porque você pode "definir regras" para os argumentos, necessária ou não, ...

ou se você é um cara Unix, do que você pode gostar porta GNU Getopt .NET .

Você pode gostar meu único Rug.Cmd

Fácil de usar e analisador de linha de comando argumento expansível. Identificadores: Bool, mais / menos, corda, Lista String, CSV, enumeração.

construído em '/?' ajuda modo.

construído em '/ ??' e '/? D' modos gerador documento.

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);
        }
    }
}

Edit: Este é o meu projeto e, como tal, esta resposta não deve ser visto como um endosso de terceiros. Que disse que eu usá-lo para cada linha de comando write programa baseado I, que é open source e é minha esperança de que outros possam se beneficiar dela.

Há uma linha analisador argumento de comando em http://www.codeplex.com/commonlibrarynet

É possível analisar os argumentos usando
1. atributos
2. chamadas explícitas
3. linha única de vários argumentos ou matriz de cadeia

Ele pode lidar com coisas como o seguinte:

- configuração : Qa - startdate : $ { hoje } - região : Settings01 'New York'

É muito fácil de usar.

Este é um manipulador que eu escrevi com base na classe Options Novell.

Este é destinado a aplicativos de console que executam um loop estilo while (input !="exit"), um console interativo, como um console de FTP por exemplo.

Exemplo de utilização:

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();
    }
}

E a fonte:

/// <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;
    }
}

O meu favorito é 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;
}

Recentemente, deparei O FubuCore Comando implementação linha de análise eu realmente gosto dele, as razões de ser:

  • é fácil de usar - embora eu não poderia encontrar uma documentação para ele, a solução FubuCore também fornece um projeto contendo um bom conjunto de testes de unidade que falam mais sobre a funcionalidade do que qualquer documentação poderia
  • tem um bom projeto orientado a objetos, sem repetição de código ou outras coisas que eu costumava ter na minha linha de comando análise de aplicativos
  • é declarativa: você aulas basicamente gravação para os comandos e conjuntos de parâmetros e decorá-los com atributos para definir várias opções (por exemplo, nome, descrição, obrigatória / opcional)
  • a biblioteca ainda imprime um bom uso Graph, com base nessas definições

Abaixo está um exemplo simples de como usar isso. Para ilustrar o uso, eu escrevi um utilitário simples que tem dois comandos: - add (adiciona um objeto a uma lista - um objeto consiste de um nome (string), valor (int) e um sinalizador booleano) - list (lista todos os objetos atualmente adicionados)

Primeiro de tudo, eu escrevi uma classe de comando para o comando 'Adicionar':

[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 leva um exemplo CommandInput como parâmetro, então eu definir o próximo:

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; }
}

O próximo comando é 'lista', que é implementado da seguinte forma:

[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;
    }
}

O comando 'list' não tem parâmetros, então eu definida uma classe NullInput para isso:

public class NullInput { }

Tudo o que resta agora é ligar isso no método Main (), assim:

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

        var executor = new CommandExecutor(factory);

        executor.Execute(args);
    }

O programa funciona como esperado, impressão de dicas sobre o uso correto no caso de quaisquer comandos são inválidos:

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

E um uso de exemplo para o comando 'Adicionar':

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
  -------------------------------------

PowerShell commandlets.

A processar feito por powershell com base em atributos especificados nas commandlets, suporte para validações, conjuntos de parâmetros, pipelining, o relatório de erros, ajuda e melhor de tudo retornando objetos .NET para uso em outros commandlets.

casal liga um i encontrado útil começar:

C # CLI é uma linha de comando biblioteca argumento de análise muito simples que eu escrevi. É bem documentado e de código aberto.

Genghis Command Line Analisador pode ser um pouco fora da data, mas é muito recurso completo e funciona muito bem para mim.

Gostaria de sugerir a biblioteca de código aberto CSharpOptParse . É analisa a linha de comando e hidrata um objecto .NET definida pelo utilizador com a entrada de linha de comando. Eu sempre recorrer a esta biblioteca ao escrever um aplicativo C # console.

Por favor, use a porta .net dos apache commons API cli. Isso funciona muito bem.

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

e a API original para conceitos e introdução

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

Um muito simples fácil de usar classe ad hoc para a linha de comando de análise, que os argumentos suportes padrão.

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 em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top