views:

5472

answers:

6

We have a C# service that is deployed to a remote customer system. The application writes a substantial amount of "diagnostic" information to the console (i.e. Console.WriteLine()). The service isn't "doing what it should." How can we capture the console output from the service in another application?

A WinForm version the application can be loaded at the customer location. It, unfortunately, functions correctly.

Update:

We are able to change the change the service, but would prefer not to make major changes at this time.

We are also logging to MSMQ, but only for "important" events. This service does interact with MSMQ for its normal operations. Or, at least, it should. The service doesn't seem to be pulling items from MSMQ when the WinForm version does. So, writing the messages that are going to the console could be problematic.

+7  A: 

Are you able to change the service code at all? If so, using Console.SetOut to write to a file instead would be the most obvious first port of call. Then change to using a proper logging library for the next release :)

Jon Skeet
Using Console.SetOut was a minimal enough change that yielded enough information to determine the problem with the service.
Mike Chess
+2  A: 

I wouldn't use Console.WriteLine at all from a Window Service. You should probably log these errors to a log file.

Another way of doing this so that multiple applications can consume the logs is posting the log messages to a MSMQ queue.

Patrik
+2  A: 

use debug.writeline and use sysinternals debugview?

Danimal
or log4net next time and configure the destination.
kenny
+1  A: 

You've got a bunch of options; redirecting console output to a file and using a proper logging library as mentioned are two good ones. Here's a middle option: write to the event log.

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".

Michael Petrotta
+3  A: 

In general, you should avoid writing diagnostic information directly to Console, the Event Log, MSMQ or elsewhere from your application code. Instead call a logging API, and use configuration to redirect the output wherever you want.

For example, you could replace all the Console.WriteLine by Trace.WriteLine (*). Then you can redirect output to the console, a file or elsewhere by modifying the application configuration file: for example to output to the console, use a ConsoleTraceListener, something like:

<configuration>
  <system.diagnostics>
    <trace autoflush="false" indentsize="4">
      <listeners>
        <add name="configConsoleListener"
             type="System.Diagnostics.ConsoleTraceListener" />
      </listeners>
    </trace>
  </system.diagnostics>
 </configuration>

While debugging, you'll get your output on the console - on the customer site you'd configure it to redirect the trace output to a file, to the event log or similar.

Even better, use a 3rd party logging framework (I'd recommend Log4Net) which will give you more options than System.Diagnostics.Trace.

(*) Trace.Write/Trace.WriteLine are the same as Debug.Write/Debug.WriteLine, except that the latter are only compiled if the DEBUG symbol is defined. So prefer Trace to Debug if you want the output to be available in Release builds.

Joe
A: 

I found this post on MSDN which binds the Console output to a rich text box, worked for me very quickly and easily.

It overrides WriteLine, and could be expanded to override other methods.

Marc