2009-05-07 20 views
20

Wie kann ein Befehlszeilen-Tool als C# -Konsolenanwendung implementiert und entworfen werden?Korrekter Weg zur Implementierung der C# -Konsolenanwendung?

Bedenken zu adressieren gehören ordnungsgemäß analysieren von Befehlszeilenvariablen und die richtige Möglichkeit, Text auszugeben. Während Console.WriteLine() die offensichtlichste Wahl für die Ausgabe ist, unter welchen Umständen sollte man stattdessen entscheiden, in den Standard-Fehlerstrom zu schreiben, .Error, .SetErrorStream, etc?

Wie kann die Anwendung ordnungsgemäß beendet werden, während ein ordnungsgemäßer Rückkehrcode an den aufrufenden Befehl zurückgegeben wird?

Wie sollte das CancelKeyPress-Ereignis implementiert werden, um das Programm zu unterbrechen? Wird es nur verwendet, wenn eine asynchrone Operation in einem separaten Thread ausgeführt wird?

Gibt es eine kurze Anleitung zur Programmierung von Befehlszeilenprogrammen in C# oder besser noch ein Open Source-Projekt oder eine Vorlage, mit der ich ein relativ einfaches Werkzeug implementieren kann?

+0

betrügen? Siehe hier: http://stackoverflow.com/questions/817673/architectural-considerations-in-designing-console-applications –

+0

Siehe auch: http://stackoverflow.com/questions/664533/best-command-line-option- Parser-for-cc-and-c-closed –

+1

Meine Frage ist eine breitere Erkundung der .NET-Konsole Anwendungs-Mechanik - einschließlich der richtigen Möglichkeit, ErrorStream und CancelKeyPress Ereignisse zu verwenden. Diese beiden Beiträge beziehen sich speziell auf das Parsen von Befehlszeilen und die Klassenstruktur. – James

Antwort

25

Fehlermeldungen sollten in stderr aka Console.Error geschrieben werden, und normale Ausgabe auf stdout alias Console.Out. Dies ist besonders wichtig für Konsolenanwendungen vom Typ "Filter", deren Ausgabe (stdout) an einen anderen Prozess weitergeleitet werden kann, z. in einer Batch-Datei.

Wenn Sie einen Fehler feststellen, schreiben Sie eine Fehlermeldung an Console.Error und geben ein Ergebnis ungleich Null zurück. Oder wenn es eine Ausnahme ist, kümmern Sie sich einfach nicht darum.

Um einen Ergebniscode zurückzugeben, können Sie ihn entweder als Argument an Environment.Exit übergeben, die Environment.ExitCode-Eigenschaft festlegen oder einen Wert ungleich Null von main zurückgeben.

Für einfache Konsole apps Ich würde:

  • eine Hilfsklasse haben die Befehlszeile zu analysieren.

  • haben eine Fassadenklasse, die eine testbare API für die von Ihrem Befehlszeilentool implementierte Funktionalität bereitstellt. Wie bei den meisten .NET-APIs würde dies normalerweise eine Ausnahme auslösen, wenn ein Fehler auftritt.

  • Das Hauptprogramm verwendet einfach den Helper, um die Befehlszeile zu analysieren, und ruft die API auf, die die von der Befehlszeile übergebenen Argumente übergibt. Es fängt optional von der API geworfene Ausnahmen ab, protokolliert sie, schreibt eine benutzerorientierte Fehlermeldung an Console.Error und setzt einen Rückkehrcode ungleich null.

Aber ich wouln't halte dies für die einzig wahre Weg sein: Es nicht wirklich so etwas ist, das ist, warum Sie unwahrscheinlich sind, das Buch zu finden, die Sie suchen.

2

Wie für Befehlszeilenargumente, finden Sie verschiedene Programme finden, aber ich habe immer ein Fan von

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

Wie für den Return-Code gewesen, können Sie die Signatur Ihrer Main() Funktion ändern zurückzukehren ein int eher als void. Dadurch können Sie bei Bedarf einen Code an den aufrufenden Prozess zurückgeben.

Wie für den Fehler-Stream, ich habe es nie persönlich verwendet, und ich denke nicht, dass es auf Kosten der Ausgabe von Fehlerinformationen im Standard-Ausgabestream kommen sollte. Es ist wahrscheinlich besser für spezifische Fehlersuchinformationen geeignet.

5

Wie zu implementieren, Befehlsanalyse, ich habe erfolgreich verwendet Reflexion und Delegaten zuvor. Sie funktioniert so, auf Befehl Methoden mit einem speziellen Attribut dekorieren Sie selbst machen, die die Methode Staaten sollten Benutzer aufrufbaren sein, entweder durch den Namen des Verfahrens oder eine Zeichenfolge in dem Attribut angegeben, das heißt:

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

On Programm startup können Sie eine Klasse nach solchen Methoden durchsuchen und Delegaten, die auf sie abzielen, in einem Wörterbuch speichern, in dem die Schlüssel die Befehle sind. Dies vereinfacht das Parsen von Befehlen basierend auf dem Nachschlagen des ersten Wortes in einem Wörterbuch (amortized O (1)) und leicht erweiterbar und für die Zukunft machbar, da neue Befehle hinzugefügt werden, die einfach separate Methoden hinzufügen.

2

Überprüfen Sie für die Befehlszeilenbehandlung Mono.GetOptions. Es erleichtert das Auffüllen von Variablen aus den Befehlszeilenoptionen short (-f style) und long (--file style).

0

Ich habe mich dafür entschieden, eine Reihe von Konsolen-Utility-Apps als Windows-Anwendungen anstelle von Konsolen-Apps zu schreiben. Im Allgemeinen füge ich einen Timer hinzu, um den Anfangsstart zu verzögern, und füge einfach eine Abbrechen-Schaltfläche mit einer Fortschrittsanzeige hinzu - wodurch eine intuitivere Abbruchoption ermöglicht wird. Sie können auf diese Weise weiterhin auf die Konsole ausgeben.

Verwandte Themen