2008-09-14 12 views
10

necesito consejos sobre cómo tener mi C# aplicación de consola de visualización de texto al usuario a través de la salida estándar sin dejar de ser capaz de acceder más tarde. La característica real que me gustaría implementar es descargar todo el buffer de salida a un archivo de texto al final de la ejecución del programa.Cómo guardar la salida de una aplicación de consola

La solución alternativa que uso mientras no encuentro un enfoque más limpio es la subclase TextWriter anulando los métodos de escritura para que ambos escriban en un archivo y llamen al escritor original de stdout. Algo como esto:

public class DirtyWorkaround { 
    private class DirtyWriter : TextWriter { 
    private TextWriter stdoutWriter; 
    private StreamWriter fileWriter; 

    public DirtyWriter(string path, TextWriter stdoutWriter) { 
     this.stdoutWriter = stdoutWriter; 
     this.fileWriter = new StreamWriter(path); 
    } 

    override public void Write(string s) { 
     stdoutWriter.Write(s); 

     fileWriter.Write(s); 
     fileWriter.Flush(); 
    } 

    // Same as above for WriteLine() and WriteLine(string), 
    // plus whatever methods I need to override to inherit 
    // from TextWriter (Encoding.Get I guess). 
    } 

    public static void Main(string[] args) { 
    using (DirtyWriter dw = new DirtyWriter("path", Console.Out)) { 
     Console.SetOut(dw); 

     // Teh codez 
    } 
    } 
} 

ver que se escribe en el archivo y elimina todo el tiempo. Me encantaría hacerlo solo al final de la ejecución, pero no pude encontrar ninguna forma de acceder al buffer de salida.

Además, excuse las imprecisiones con el código anterior (tuvo que escribirlo ad hoc, lo siento;).

Respuesta

5

La solución perfecta para esto es utilizar log4net con una consola y un appender appender archivo. También hay muchos otros apéndices disponibles. También le permite apagar y encender los diferentes apéndices en tiempo de ejecución.

+0

¡Muy buena idea! De hecho, lo que necesito es un registrador. De esa manera puedo almacenar mucha más información que la que se muestra simplemente al usuario (y le molesto mucho menos). Muchas veces la mejor solución proviene de un enfoque diferente, proveniente de alguien externo al problema. –

+2

Creo que en este caso puede ser excesivo usar una biblioteca de terceros cuando puede requerir solo una pequeña cantidad de trabajo agregar la funcionalidad necesaria al sistema. – Wedge

+3

Acepto que log4net es una dependencia bastante pesada para tomar aquí. –

4

No creo que haya nada malo con su enfoque.

Si quería código reutilizable, considere implementar una clase llamada MultiWriter o algo por el estilo que toma como entrada dos (o N?) TextWriter corrientes y distribuye todos los autos, sofocos, etc., para aquellas corrientes. Entonces puede hacer esto de archivo/consola, pero igual de fácil puede dividir cualquier flujo de salida. ¡Útil!

+0

El problema con mi enfoque es que estoy manteniendo el archivo abierto y descargándolo todo el tiempo. Y, supongo, abrir y cerrar el archivo en cada grabación sería engorroso. Sin embargo, su idea de un MultiWriter es muy ingeniosa :) –

1

Probablemente no es lo que quiere, pero por las dudas ... Aparentemente, PowerShell implements es una versión del comando venerable tee. Que es más o menos exactamente para este propósito. Entonces ... fóllalos si los tienes.

1

yo diría que imitan los diagnósticos que utiliza .NET sí (Trace y depuración).

crear una clase de "salida" que puede tener diferentes clases que se adhieren a una interfaz de salida de texto. Usted informa a la clase de salida, envía automáticamente la salida dada a las clases que ha agregado (ConsoleOutput, TextFileOutput, WhateverOutput) ... Y así sucesivamente ... Esto también lo deja abierto para agregar otros tipos de "salida" (como xml/xslt para obtener un informe muy formateado?).

Mira la Trace Listeners Collection para ver a qué me refiero.

0

Considere refaccionar su aplicación para separar las partes de interacción del usuario de la lógica de negocios. En mi experiencia, tal separación es bastante beneficiosa para la estructura de su programa.

Para el problema particular que está tratando de resolver aquí, se vuelve sencillo que la parte de interacción del usuario cambie su comportamiento de Console.WriteLine a E/S de archivos.

0

estoy trabajando en la implementación de una función similar para capturar la salida enviada a la consola y guardarlo en un registro mientras sigue pasando la salida en tiempo real a la consola normal, de modo que no se rompa la aplicación (por ejemplo. Si es una aplicación de consola!).

Si todavía está tratando de hacer esto en su propio código guardando la salida de la consola (en lugar de usar un sistema de registro para guardar solo la información que realmente le importa), creo que puede evitar el color después de cada escriba, siempre y cuando anule Flush() y asegúrese de que vacía el original stdoutWriter que guardó, así como también su fileWriter. Desea hacer esto en caso de que la aplicación intente vaciar una línea parcial a la consola para su visualización inmediata (como un mensaje de entrada, un indicador de progreso, etc.), para anular el almacenamiento en línea normal.

Si ese enfoque tiene problemas con su salida de la consola está amortiguada demasiado largo, puede que tenga que asegurarse de que WriteLine() vuelca stdoutWriter (pero probablemente no tiene que vaciar fileWriter excepto cuando su Flush() se llama anulación) . Pero creo que el Console.Out original (que en realidad va a la consola) vaciará automáticamente su buffer en una nueva línea, por lo que no debería tener que forzarlo.

También es posible que desee anular Cerrar() para (limpiar y cerrar) su fileWriter (y probablemente también stdoutWriter), pero no estoy seguro si eso es realmente necesario o si Cerrar() en el TextWriter base emita un Flush() (que ya anularía) y puede confiar en la salida de la aplicación para cerrar su archivo. Probablemente deberías probar que se enjuaga al salir, para estar seguro. Y tenga en cuenta que una salida anormal (falla) probablemente no purgue la salida almacenada en el búfer. Si eso es un problema, puede ser deseable enjuagar fileWriter en newline, pero esa es otra lata de gusanos complicada.

Cuestiones relacionadas