2009-05-07 16 views
20

¿Cuál es la forma correcta de implementar y diseñar una herramienta de línea de comandos como una aplicación de consola C#?¿Manera correcta de implementar la aplicación de consola C#?

Las preocupaciones para abordar incluyen el análisis adecuado de las variables de la línea de comando y la forma correcta de imprimir el texto. Si bien Console.WriteLine() es la elección más obvia para el resultado, ¿cuáles son las circunstancias en las que se debe optar por escribir en el flujo de error estándar, .Error, .SetErrorStream, etc.?

¿Cuál es la forma correcta para que la aplicación salga al tiempo que devuelve un código de retorno adecuado al comando de llamada?

¿Cómo se debe implementar el evento CancelKeyPress para interrumpir el programa? ¿Es solo para uso cuando una operación asincrónica está ocurriendo en un hilo separado?

¿Hay una guía concisa para la programación de herramientas de línea de comandos en C#, o mejor aún un proyecto o plantilla de código abierto que podría utilizar para implementar correctamente una herramienta relativamente simple?

+0

dupe? Consulte aquí: http://stackoverflow.com/questions/817673/architectural-considerations-in-designing-console-applications –

+0

Vea también: http://stackoverflow.com/questions/664533/best-command-line-option- parsers-for-cc-and-c-closed –

+1

Mi pregunta es una exploración más amplia de la mecánica de la aplicación de la consola .NET, incluida la forma correcta de utilizar los eventos ErrorStream y CancelKeyPress. Esas dos publicaciones se relacionan específicamente con el análisis de línea de comando y la estructura de clases, respectivamente. – James

Respuesta

25

Los mensajes de error se deben escribir en stderr también conocido como Console.Error, y la salida normal en stdout aka Console.Out. Esto es particularmente importante para las aplicaciones de consola de tipo "filtro" cuya salida (stdout) se puede canalizar a otro proceso, p. en un archivo por lotes.

Generalmente, si encuentra un error, escriba un mensaje de error a Console.Error y devuelva un resultado que no sea cero. O si es una excepción, simplemente no se moleste en manejarlo.

Para devolver un código de resultado, puede pasarlo como argumento a Environment.Exit, establecer la propiedad Environment.ExitCode o devolver un valor distinto de cero desde main.

Para aplicaciones de consola simples yo:

  • tienen una clase de ayuda a analizar la línea de comandos.

  • tienen una clase de fachada que proporciona una API comprobable para la funcionalidad implementada por su herramienta de línea de comandos. Al igual que la mayoría de las API de .NET, esto normalmente generaría una excepción si se produce un error.

  • el programa principal simplemente usa el helper para analizar la línea de comando y llama a la API pasando los argumentos pasados ​​desde la línea de comando. Opcionalmente detecta las excepciones lanzadas desde la API, las registra, escribe un mensaje de error orientado al usuario en Console.Error y establece un código de retorno distinto de cero.

Pero wouln't considero que esto es el único camino verdadero: en realidad no hay tal cosa por lo que es poco probable que encontrar el libro que está buscando.

2

En cuanto a los argumentos de línea de comandos, encontrará varios esquemas, pero siempre ha sido un fan de

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

En cuanto al código de retorno, puede cambiar la firma de su función para volver Main() un int en lugar de void. Esto le permitirá devolver un código al proceso de llamada, si es necesario.

En cuanto a la secuencia de errores, nunca la he usado personalmente, y no creo que deba ser a expensas de generar información de error en la secuencia de salida estándar. Probablemente se use mejor para la información de depuración de errores específicos.

5

En cuanto a cómo implementar el análisis de comandos, he usado con éxito la reflexión y los delegados antes. La forma en que funciona es para decorar métodos de comando con un atributo especial que usted se hace que indica el método debería ser-invocable usuario, ya sea por el nombre del método o una cadena especificada en el atributo, es decir:

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

El programa de inicio puede escanear una clase para tales métodos, y almacenar delegados que los dirigen en un diccionario donde las claves son los comandos. Esto facilita el análisis de comandos basados ​​en la búsqueda de la primera palabra en un diccionario (O (1) amortizado) y fácilmente extensibles y mantenibles para el futuro, a medida que se agregan nuevos comandos simplemente agregando métodos separados.

2

Para el manejo de línea de comandos, consulte Mono.GetOptions. Hace que sea fácil rellenar las variables desde las opciones de línea de comando corta (-f estilo) y larga (-file style).

0

He optado por escribir una serie de aplicaciones de consola para Windows como aplicaciones de Windows en lugar de aplicaciones de consola. En general, agrego un temporizador para retrasar el inicio inicial y simplemente agrego un botón de cancelar con un medidor de progreso, lo que permite una opción de cancelación más intuitiva. También puede salir a la consola de esa manera.

Cuestiones relacionadas