38

I am currently using TopShelf with a Console Application to create a Windows Service. When I run the code as a console application I use a few Console.WriteLine() to output results. Once the code does what it is supposed to do I install the console application as a Windows Service.

Are there any downsides with leaving the Console.WriteLine() code even though a Windows Service can not write to the console? Are there any risks of having unstable code if I leave the Console.WriteLine() in there?

Thomas
  • 5,888
  • 7
  • 44
  • 83
  • 4
    Although (as @dtech and @ odie pointed out), this does not cause any damage, I suggest you take a look into logging frameworks such as log4net or NLog – yas4891 Jan 09 '12 at 18:08

5 Answers5

40

The output will simply be discarded.

In a Windows Service there is no Console so Console.Write* output is discarded. There are a number of alternatives:

  1. The System.Diagnostics.Trace class has a similar interface to the Console class so you could migrate your code quite easily to this.
  2. It can then be configured to output to a file. You can use the System.Diagnostics.EventLog class to write to the Event Log which you can then monitor using Event Viewer.
  3. You can use the third-party open-source log4net library which is very flexible.
Sandeep Kumar M
  • 3,841
  • 3
  • 38
  • 59
dtech
  • 13,741
  • 11
  • 48
  • 73
9

No, the console class will safely write to the STDOUT, but you will just not see the output.

doogle
  • 3,376
  • 18
  • 23
4

If you use the System.Diagnostics.Trace functionality, you can redirect the output using the listeners and switches. If you compile with the TRACE symbol, then code will be included. If you don't add the TRACE, then it won't be compiled into the project.

If you run your services as console for debugging, the Trace will output to the console by default. I've taken to using Trace instead of Debug or Console writes since I can, from the config file, output the trace information to any combination of files, screen, database, etc.

Bill Crim
  • 612
  • 4
  • 7
  • Trace outputs to the debugger console, not the console window like `Console.WriteLine does`. Seems to me there is some confusion here about which console the OP is talking about. – ProfK Nov 13 '14 at 18:09
  • 2
    Trace can be configured to have multiple forms of output, including output to the Console via the ConsoleTraceListener. The default listener for Trace and Debug is DefaultTraceListener, which outputs to the debug console. – Bill Crim Nov 28 '14 at 22:59
3

The output was always discarded until Windows Server 2008R2. Leave a console.writeline() in a service installed on that OS, and you'll get an error 1067 when starting/running the service, depending on the position of the writeline().

Pierre
  • 114
  • 4
  • 3
    can you qualify what you mean with "depending on the position ..."? I just ran into this problem and fixed it by removing the Console-statements, but I am really puzzled over why I have never seen this before, since I have made numerous Windows Services over the years. I have confirmed the problem on Windows 2008 R2 Svr as well as Windows 7 Enterprise. – Jesper Lund Stocholm Feb 06 '15 at 07:03
1

Also want to display a help depending on command line.
My solution is to open a new console.

internal static class NativeMethods
{
    [DllImport("user32.dll")]
    internal static extern bool SetForegroundWindow(IntPtr hWnd);

    [DllImport("user32.dll")]
    internal static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);

    [DllImport("kernel32.dll")]
    internal static extern bool AllocConsole();

    [DllImport("kernel32.dll")]
    internal static extern IntPtr GetConsoleWindow();
}

public static void ShowWindow(IntPtr hWnd, ShowWindowCommand cmd = ShowWindowCommand.Restore)
{
    NativeMethods.SetForegroundWindow(hWnd);
    NativeMethods.ShowWindowAsync(hWnd, (int)cmd);
}

public static void ShowConsoleWindow()
{
    var handle = NativeMethods.GetConsoleWindow();

    if (handle == IntPtr.Zero)
        NativeMethods.AllocConsole();
    else
        ShowWindow(handle, ShowWindowCommand.Show);
}

ShowWindowCommand is just an enum built from here
https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-showwindow

Edit:
That solution worked for years but currently fails. Unclear if it is related to a Windows- or VisualStudio update. Definitly does not work on W10 20H2 and VS2019 16.9.x

TomB
  • 641
  • 5
  • 17
  • do you also need the C# `AttachConsole(-1);` call? This call works when the service is run from a console so that C# `Console.WriteLine()` calls attach to the running console., but does the one created above automatically attach so that subsequent `Console.WriteLine()` calls output as expected? – ergohack May 17 '21 at 20:22
  • @ergohack As you said AttachConsole works if you already have a console. The whole point is that a windows service does not have one :-). – TomB May 21 '21 at 06:44
  • My problem was that the VS Debugger was redirecting the Console Output to the VS Output window, ... here is the fix that I needed to move the calls to `Console.WriteLine()` back to the newly allocated console. https://stackoverflow.com/q/15604014/4151626 – ergohack Jun 02 '21 at 20:32