1

When i'm working with most projects, from winforms, consoles, WPF, if needed i can print out any information i want to check more easily at run time using a messagebox or the likes;

MessageBox.Show(whateveriwannashow);

However, i'm now working on a windows service, which doesn't allow for the presence of any sort of GUI. What direction should i head in to show some information? Does VS2010 have a built in feature for this sort of stuff?

Kestami
  • 2,045
  • 3
  • 32
  • 47

4 Answers4

3

System.Diagnostics.Trace is your new best friend. Trace is output directly to the output window in Visual Studio, can be send to the logger or can be viewed using free third-party tools like SysInternals DebugView.

For debug work it beats logging hands down. here's why:

  1. It won't leave great big log files on your drive. This means you can be really granular with trace and not leave big files on the disk.
  2. If nothing is listening to the trace output it is basically lost in the ether.
  3. You can watch the output in real-time using DebugView (and Exe with no external dependencies)
  4. If you want to log it you can simply add a trace listener to your logger
  5. It's easy to set up
  6. It writes to the output window by default.
Faster Solutions
  • 7,005
  • 3
  • 29
  • 45
  • I was looking for something like this : ) Look so much more lightweight and on-the-go than other options. Thanks! Will take a look into this shortly. – Kestami Dec 12 '12 at 09:46
2

You have a few options:

Database Log: Preferably the service should write to the database log and you should write a separate application that can display the entries and help you make sense of them. This approach can be problematic however because if the database goes down you'll lose any log entries that should have been made in the mean time.

File Log: More reliable writing but more difficult to access from multiple locations. Unless you plan on putting them into some central log folder that's used by a number of other applications it can be easy to forget where they reside and consequently they're usually ignored.

In Memory Log: Allowing a client application to communicate with the service and get some log information can be a good approach but then there's no permanent record. Depending on how soon someone would notice if the service went down this approach may not be the best.

In the end, each approach has it's benefits. Personally I prefer to write to the database first and cascade to a file log when the database writes fail. In memory logs would be strictly reserved for debug messages and would flush out old entries once it got up to something sizable.

Spencer Ruport
  • 34,865
  • 12
  • 85
  • 147
1

You should use logs.

How about logging using a third party library that abstracts how the text log is physically stored? You could then configure your service app.config to use any sort of log output:

  • database
  • rolling flat file
  • XML file
  • windows event log

without having to modify your code.

You could use Enterprise Library or log4net for instance.

ken2k
  • 48,145
  • 10
  • 116
  • 176
1

For (semi)persistent information, I fully agree with Spencer. But if you need some quick runtime info for debugging/tracing purposes, you can "hijack" a commandline window and write to it.

protected override OnStart(string[] args)
{
    int processId;
    IntPtr ptr = GetForegroundWindow();
    GetWindowThreadProcessId(ptr, out processId);
    var process = Process.GetProcessById(processId);

    if (String.CompareOrdinal(process.ProcessName, "cmd") == 0)
    {
        // Hijack an existing foreground cmd window.
        AttachConsole(process.Id);
    }
    else
    {
        // Or create a new one
        AllocConsole();
    }
}

protected override OnStop()
{
    FreeConsole();
}

[DllImport("kernel32.dll", SetLastError = true)]
static extern bool AllocConsole();

[DllImport("kernel32.dll", SetLastError = true)]
static extern bool FreeConsole();

[DllImport("kernel32", SetLastError = true)]
static extern bool AttachConsole(int dwProcessId);

[DllImport("user32.dll")]
static extern IntPtr GetForegroundWindow();

[DllImport("user32.dll", SetLastError = true)]
static extern uint GetWindowThreadProcessId(IntPtr hWnd, out int lpdwProcessId);

Then you can use the console for your output, ideally with 3rd party logging systems like log4net. In my scenario the setup looked like:

//Enable log4net logging into the console
ConsoleAppender appender = new ConsoleAppender {Layout = new SimpleLayout()};
BasicConfigurator.Configure(appender);

But that part is log4net-specific. You should be able to use even Console.Write(), although it's much harder to set up.

What I like about this is that you can "bind" it to commandline/config parameters of the service and the 3rd party logger will just switch logging from its default location to the console, if you set it up so. No need to do any further checks in code. Also you can do this anywhere - in your dev machine, on a remote server...

Anyway, as I said in the beginning, if you don't really need realtime information, I'd stick with Spencer's advice.

Honza Brestan
  • 10,637
  • 2
  • 32
  • 43