2009-05-07 15 views
20

Qual è il modo corretto di implementare e progettare uno strumento da riga di comando come un'applicazione console C#?Modo corretto per implementare l'applicazione console C#?

Le preoccupazioni per l'indirizzo includono l'analisi corretta delle variabili della riga di comando e il metodo corretto per l'output del testo. Mentre Console.WriteLine() è la scelta più ovvia per l'output, quali sono le circostanze in cui si dovrebbe invece scegliere di scrivere nel flusso di errori standard, .Error, .SetErrorStream, ecc.?

Qual è il modo corretto per l'uscita dell'applicazione durante la restituzione di un codice di ritorno corretto al comando di chiamata?

Come deve essere implementato l'evento CancelKeyPress per interrompere il programma? È solo per l'uso quando si verifica un'operazione asincrona su un thread separato?

Esiste una guida concisa alla programmazione degli strumenti a riga di comando in C#, o ancora meglio un progetto o un modello open source che potrei utilizzare per implementare correttamente uno strumento relativamente semplice?

+0

dupe? Vedi qui: http://stackoverflow.com/questions/817673/architectural-considerations-in-designing-console-applications –

+0

Vedi anche: http://stackoverflow.com/questions/664533/best-command-line-option- parsers-for-cc-and-c-closed –

+1

La mia domanda è un'esplorazione più ampia della meccanica delle applicazioni della console .NET, incluso il modo corretto di usare gli eventi ErrorStream e CancelKeyPress. Questi due post riguardano in particolare l'analisi della riga di comando e la struttura della classe, rispettivamente. – James

risposta

25

I messaggi di errore devono essere scritti su stderr alias Console.Error e output normale su stdout, ovvero Console.Out. Ciò è particolarmente importante per le app di console di tipo "filtro" il cui output (stdout) può essere collegato a un altro processo, ad es. in un file batch.

In genere se si verifica un errore, scrivere un messaggio di errore su Console.Error e restituire un risultato diverso da zero. O se è un'eccezione, non preoccuparti di gestirla.

Per restituire un codice risultato, è possibile passarlo come argomento a Environment.Exit, impostare la proprietà Environment.ExitCode o restituire un valore diverso da zero dal main.

Per semplici applicazioni console avrei:

  • hanno una classe di supporto per analizzare la riga di comando.

  • hanno una classe di facciata che fornisce un'API testabile per la funzionalità implementata dal tuo strumento da riga di comando. Come la maggior parte delle API .NET, questo genererebbe normalmente un'eccezione se si verifica un errore.

  • il programma principale utilizza semplicemente l'helper per analizzare la riga di comando e chiama l'API passando gli argomenti passati dalla riga di comando. Opzionalmente cattura le eccezioni generate dall'API, le registra, scrive un messaggio di errore orientato all'utente su Console.Error e imposta un codice di ritorno diverso da zero.

Ma io wouln't che questo sia l'unico vero modo: non c'è davvero una cosa del genere, che è il motivo per cui è improbabile per trovare il libro che stai cercando.

2

Per quanto riguarda gli argomenti della riga di comando, troverete vari schemi, ma io sono sempre stato un fan di

app.exe "self-explanatory arg" /noArgumentSwitch /argumentSwitch="argument" 

Per quanto riguarda il codice di ritorno, è possibile modificare la firma della funzione Main() per tornare uno int anziché void. Ciò ti consentirà di restituire un codice al processo chiamante, se necessario.

Per quanto riguarda il flusso di errori, non l'ho mai utilizzato personalmente e non penso che ciò debba avvenire a scapito dell'emissione di informazioni di errore nel flusso di output standard. Probabilmente è meglio utilizzato per specifiche informazioni di debug degli errori.

5

Per quanto riguarda l'implementazione dell'analisi dei comandi, in passato ho utilizzato correttamente i parametri di riflessione e delegati. Essi modo in cui funziona è quello di decorare metodi di comando con un attributo speciale ti fai che indica il metodo dovrebbe essere user-richiamabile, sia attraverso il nome del metodo o una stringa specificata nell'attributo, vale a dire:

[Command("quit")] 
public void QuitApp() 
{ 
    ... 
} 

Sul programma all'avvio è possibile eseguire la scansione di una classe per tali metodi e memorizzare i delegati che li indirizzano in un dizionario in cui le chiavi sono i comandi. Ciò semplifica l'analisi dei comandi basati sulla ricerca della prima parola in un dizionario (O (1) ammortizzato e facilmente estensibile e controllabile per il futuro, con l'aggiunta di nuovi comandi semplicemente aggiungendo metodi separati.

2

Per la gestione della riga di comando, selezionare Mono.GetOptions. Semplifica la compilazione di variabili da opzioni di riga di comando brevi (-f stile) e lunghe (-file stile).

0

Ho deciso di scrivere un numero di app di utilità per console in cui Windows forma applicazioni anziché app per console. In genere, aggiungo un timer per ritardare l'avvio iniziale e basta aggiungere un pulsante di annullamento con un indicatore di avanzamento, consentendo così un'opzione di annullamento più intuitiva. È comunque possibile eseguire l'output anche sulla console.

Problemi correlati