Cómo capturar la salida de la consola de un servicio C #?

Tenemos un servicio de C# que se implementa en un sistema de cliente remoto. La aplicación escribe una cantidad sustancial de información de "diagnóstico" en la consola (es decir, Console.WriteLine ()). El servicio no está "haciendo lo que debería". ¿Cómo podemos capturar la salida de la consola del servicio en otra aplicación?

Una versión de WinForm la aplicación se puede cargar en la ubicación del cliente. Desafortunadamente, funciona correctamente.

Actualizar:

Podemos cambiar el cambio del servicio, pero preferiríamos no realizar cambios importantes en este momento.

También estamos iniciando sesión en MSMQ, pero solo para eventos "importantes". Este servicio interactúa con MSMQ para sus operaciones normales. O al menos debería. El servicio no parece extraer elementos de MSMQ cuando lo hace la versión de WinForm. Entonces, escribir los mensajes que van a la consola podría ser problemático.

18

7 Respuestas

¿Puedes cambiar el código de servicio en todo ? Si es así, usar Console.SetOut para escribir en un archivo sería el primer puerto de escala más obvio. Luego cambie a usar una biblioteca de registro apropiada para la próxima versión :)

31
agregado
El uso de Console.SetOut fue un cambio lo suficientemente mínimo que proporcionó información suficiente para determinar el problema con el servicio.
agregado el autor Mike Chess, fuente

En general, debe evitar escribir información de diagnóstico directamente en la consola, el registro de eventos, MSMQ u otro lugar desde el código de la aplicación. En su lugar, llame a una API de registro y use la configuración para redirigir el resultado donde desee.

Por ejemplo, puede reemplazar todas las Console.WriteLine por Trace.WriteLine (*). A continuación, puede redirigir la salida a la consola, a un archivo u otro lugar modificando el archivo de configuración de la aplicación: por ejemplo, para enviar a la consola, use un ConsoleTraceListener, algo así como:


  
    <trace autoflush="false" indentsize="4">
      
        
      
    
  
 

Durante la depuración, obtendrá su resultado en la consola: en el sitio del cliente, lo configuraría para redirigir la salida de rastreo a un archivo, al registro de eventos o similar.

Mejor aún, use un marco de registro de terceros (recomendaría Log4Net) que le ofrecerá más opciones que System.Diagnostics.Trace.

(*) Trace.Write/Trace.WriteLine es lo mismo que Debug.Write/Debug.WriteLine, excepto que estos últimos solo se compilan si se define el símbolo DEBUG. Por lo tanto, prefiera Trace a Debug si desea que la salida esté disponible en las compilaciones de Release.

12
agregado

Tienes un montón de opciones; redirigir la salida de la consola a un archivo y usar una biblioteca de registro apropiada como se mencionó son dos buenas. Aquí hay una opción del medio: escriba en el registro de eventos.

EventLog log;
string logsource = "MyService";

// execute once per invocation
if (!System.Diagnostics.EventLog.SourceExists(logsource))
{
    System.Diagnostics.EventLog.CreateEventSource(
        logsource, "Application");
}
log = new EventLog();
log.Source = logsource;
log.Log = "Application";

// replace console logging with this
log.WriteEntry(message, EventLogEntryType.Information);

Then look for entries in the Application event log (Administrative Tools -> Event Viewer) where Source = "MyService".

5
agregado

usar debug.writeline y usar debugview sysinternals?

3
agregado
o log4net la próxima vez y configure el destino.
agregado el autor kenny, fuente

No usaría Console.WriteLine en absoluto desde un Servicio de Ventanas. Probablemente deberías registrar estos errores en un archivo de registro.

Otra forma de hacerlo para que varias aplicaciones puedan consumir los registros es publicar los mensajes de registro en una cola de MSMQ.

3
agregado

Encontré esta publicación en MSDN, que vincula la salida de la Consola a un cuadro de texto enriquecido, me funcionó muy rápida y fácilmente.

Anula WriteLine y podría expandirse para anular otros métodos.

1
agregado

Así es como vi la salida de la consola de un servicio que se ejecuta bajo Windows 7. Esto podría ayudar si no puede modificar el código fuente del servicio para iniciar sesión en un archivo.

  1. Ejecute services.msc y edite las propiedades del servicio. En la pestaña "Iniciar sesión", marca "Permitir que el servicio interactúe con el escritorio"

  2. Utilice el editor de registro para modificar ImagePath de su servicio: vaya a HKEY_LOCAL_MACHINE \ SYSTEM \ ControlSet001 \ services \ [su nombre de servicio] y edite ImagePath. Agregue cmd.exe/c al comienzo de la cadena de ImagePath. Entonces, si su ImagePath original es c: \ myService \ myservice.exe su nuevo ImagePath debe ser cmd.exe /cc:\myService\myservice.exe.

  3. Comience su servicio. Debería obtener una ventana emergente titulada "Detección de servicios interactivos". Seleccione "Ver el mensaje". Su pantalla debe cambiar contextos y mostrar la ventana de la consola. Cuando termine, haga clic en el botón "Volver ahora".

  4. Cuando termine de depurar, modifique ImagePath a su valor original. A continuación, desmarque la casilla "Permitir que el servicio interactúe con el escritorio" en las propiedades del servicio y reinicie su servicio.

Advertencia: solo he hecho esto con un servicio y funcionó para mí. No sé si funcionará para cualquier servicio o si causará resultados inesperados, por lo que le sugiero que solo lo haga en un entorno que no sea de producción.

1
agregado