Domanda

Quando crei applicazioni console che accettano parametri, puoi utilizzare gli argomenti passati a Main(string[] args).

In passato ho semplicemente indicizzato/eseguito il loop dell'array e ho eseguito alcune espressioni regolari per estrarre i valori.Tuttavia, quando i comandi diventano più complicati, l'analisi può risultare piuttosto complessa.

Quindi mi interessa:

  • Librerie che usi
  • Modelli che usi

Supponiamo che i comandi aderiscano sempre a standard comuni come risposto qui.

È stato utile?

Soluzione

Suggerirei vivamente di utilizzare NDesk.Options ( Documentazione ) e / o Mono.Options (stessa API, spazio dei nomi diverso). An esempio dalla documentazione :

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

Altri suggerimenti

Mi piace molto la libreria del parser della riga di comando ( http://commandline.codeplex.com/ ). Ha un modo molto semplice ed elegante di impostare parametri tramite attributi:

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 libreria WPF TestApi include uno dei migliori parser della riga di comando per lo sviluppo di C #. Consiglio vivamente di esaminarlo, dal Blog di Ivo Manolov sull'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);

Sembra che ognuno abbia il proprio parser da riga di comando, immagino che farei meglio ad aggiungere anche il mio :).

http://bizark.codeplex.com/

Questa libreria contiene a analizzatore della riga di comando che inizializzerà una classe con i valori dalla riga di comando.Ha un sacco di funzionalità (l'ho sviluppato nel corso di molti anni).

Dal documentazione...

L'analisi della riga di comando nel framework BizArk presenta queste caratteristiche principali:

  • Inizializzazione automatica: Le proprietà della classe vengono impostate automaticamente in base agli argomenti della riga di comando.
  • Proprietà predefinite: Invia un valore senza specificare il nome della proprietà.
  • Conversione di valore: Utilizza la potente classe ConvertEx inclusa anche in BizArk per convertire i valori nel tipo corretto.
  • Flag booleani: I flag possono essere specificati semplicemente utilizzando l'argomento (ad esempio, /b per vero e /b- per falso) o aggiungendo il valore vero/falso, sì/no, ecc.
  • Matrici di argomenti: Aggiungi semplicemente più valori dopo il nome della riga di comando per impostare una proprietà definita come array.Esempio: /x 1 2 3 popolerà x con l'array { 1, 2, 3 } (assumendo che x sia definito come un array di numeri interi).
  • Alias ​​della riga di comando: Una proprietà può supportare più alias della riga di comando.Ad esempio, la Guida utilizza l'alias ?.
  • Riconoscimento parziale del nome: Non è necessario scrivere il nome completo o l'alias, basta scriverne abbastanza perché il parser possa disambiguare la proprietà/alias dagli altri.
  • Supporta ClickOnce: Può inizializzare le proprietà anche quando sono specificate come stringa di query in un URL per le applicazioni distribuite ClickOnce.Il metodo di inizializzazione della riga di comando rileverà se è in esecuzione come ClickOnce o meno, quindi non è necessario che il codice venga modificato quando lo si utilizza.
  • Crea automaticamente /?aiuto: Ciò include una formattazione gradevole che tenga conto della larghezza della console.
  • Carica/salva gli argomenti della riga di comando in un file: Ciò è particolarmente utile se disponi di più set grandi e complessi di argomenti della riga di comando che desideri eseguire più volte.

Ho scritto un parser argomento della riga di comando C # qualche tempo fa. È disponibile all'indirizzo: http://www.codeplex.com/CommandLineArguments

CLAP (parser di argomenti della riga di comando) ha un'API utilizzabile ed è meravigliosamente documentata. Si crea un metodo, annotando i parametri. https://github.com/adrianaisemberg/CLAP

Esistono numerose soluzioni a questo problema. Per completezza e per fornire l'alternativa se qualcuno desidera, sto aggiungendo questa risposta per due utili lezioni nel mio libreria di codici google .

Il primo è ArgumentList che è responsabile solo dell'analisi dei parametri della riga di comando. Raccoglie coppie nome-valore definite dagli switch '/ x: y' o '-x = y' e raccoglie anche un elenco di voci 'senza nome'. È fondamentale l'uso è discusso qui , visualizza la classe qui .

La seconda parte è CommandInterpreter che crea un'applicazione da riga di comando completamente funzionale fuori dalla tua classe .Net. Ad esempio:

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 il codice di esempio sopra puoi eseguire quanto segue:

  

Program.exe DoSomething " valore stringa " 5

- oppure -

  

Dosomething / ivalue Program.exe = 5 -svalue: " valore stringa "

È semplice o complesso quanto basta. Puoi rivedere il codice sorgente , visualizza la guida o scarica il binario .

Mi piace quello , perché puoi " definire le regole " per gli argomenti, necessari o no, ...

o se sei un tipo Unix, potresti apprezzare la porta GNU Getopt .NET .

Potrebbe piacerti il ​​mio Tappeto.Cmd

Parser di argomenti della riga di comando facile da usare ed espandibile.Maniglie:Bool, Più/Meno, Stringa, Elenco stringhe, CSV, Enumerazione.

Costruito in '/?' Modalità di aiuto.

Incorporato in '/??' e '/? D' modalità generatore di documenti.

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

Modificare:Questo è il mio progetto e come tale questa risposta non dovrebbe essere vista come un'approvazione da parte di terzi.Detto questo, lo uso per ogni programma basato su riga di comando che scrivo, è open source e spero che altri possano trarne beneficio.

Esiste un parser di argomenti della riga di comando in http://www.codeplex.com/commonlibrarynet

Può analizzare gli argomenti usando
1. attributi
2. chiamate esplicite
3. riga singola di più argomenti o array di stringhe

Può gestire cose come le seguenti:

- config : Qa - data di inizio : $ { oggi } - regione : Impostazioni "New York "01

È molto facile da usare.

Questo è un gestore che ho scritto basato sulla classe Novell Options.

Questo è rivolto ad applicazioni console che eseguono un ciclo di stile while (input !="exit"), ad esempio una console interattiva come una console FTP.

Esempio di utilizzo:

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

Il mio preferito è http://www.codeproject.com/KB/recipes/ plossum_commandline.aspx di 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;
}

Di recente mi sono imbattuto nella riga di comando di FubuCore analizzando l'implementazione Mi piace molto, i motivi sono:

  • è facile da usare - anche se non sono riuscito a trovare una documentazione per esso, la soluzione FubuCore fornisce anche un progetto contenente un bel set di Test unit che parlano più delle funzionalità di quanto qualsiasi documentazione potrebbe
  • ha un bel design orientato agli oggetti, nessuna ripetizione del codice o altre cose simili che avevo nella mia riga di comando per l'analisi delle app
  • è dichiarativo: in pratica scrivi le classi per i Comandi e gli insiemi di parametri e li decora con attributi per impostare varie opzioni (ad es. nome, descrizione, obbligatorio / opzionale)
  • la biblioteca stampa persino un bel grafico di utilizzo, basato su queste definizioni

Di seguito è riportato un semplice esempio su come utilizzarlo. Per illustrare l'utilizzo, ho scritto una semplice utility che ha due comandi: - aggiungi (aggiunge un oggetto a un elenco - un oggetto è costituito da un nome (stringa), un valore (int) e un flag booleano) - list (elenca tutti gli oggetti attualmente aggiunti)

Prima di tutto, ho scritto una classe Command per il comando 'add':

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

Questo comando utilizza un'istanza CommandInput come parametro, quindi lo definisco successivamente:

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

Il comando successivo è 'list', che è implementato come segue:

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

Il comando 'list' non accetta parametri, quindi ho definito una classe NullInput per questo:

public class NullInput { }

Ora non resta che collegarlo nel metodo Main (), in questo modo:

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

        var executor = new CommandExecutor(factory);

        executor.Execute(args);
    }

Il programma funziona come previsto, stampando suggerimenti sull'uso corretto in caso di comandi non validi:

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

E un esempio di utilizzo per il comando 'aggiungi':

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

Comandi Powershell.

Analisi effettuata da PowerShell in base agli attributi specificati nei comandi, supporto per convalide, set di parametri, pipeline, segnalazione errori, guida e, soprattutto, restituendo oggetti .NET da utilizzare in altri comandi.

Un paio di link che ho trovato utili per iniziare:

CLI C # è una libreria di analisi degli argomenti da riga di comando molto semplice che ho scritto. È ben documentato e open source.

Genghis Command Line Parser potrebbe essere un po 'obsoleto, ma è molto funzione completa e funziona abbastanza bene per me.

Suggerirei la libreria open source CSharpOptParse . Analizza la riga di comando e idrata un oggetto .NET definito dall'utente con l'input della riga di comando. Mi rivolgo sempre a questa libreria quando scrivo un'applicazione console C #.

Utilizza la porta .net dell'API cli di apache commons. Funziona benissimo.

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

e l'API originale per concetti e introduzione

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

Una classe ad hoc molto semplice e facile da usare per l'analisi della riga di comando, che supporta argomenti predefiniti.

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"));
    }
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top