Run a Windows Service as a console app

When working on a Windows Service project you may want to run it as a Console App so you can see what’s going on.

If you try to run the service in Visual Studio you’ll get an error that says: “Cannot start service from the command line or a debugger. A Windows Service must first be installed… .”

You really only have two options:

  1. Install the service and look at the logs. This is tedious and slows down development.
  2. Conditionally run the program as a console app

In this article I’ll explain how to run it as a console app.

1 – Set the project output type to Console Application

Check which scenario below matches your situation.

Note: If you don’t change your output type to Console App you’ll get an exception “System.InvalidOperationException: ‘Cannot read keys when either application does not have a console or when console input has been redirected from a file. Try Console.Read.’

If you already have a Windows Service project

Simply change the Output type to Console Application.

If you are starting a new project from scratch

Create a Windows Service project. Then change the Output type to Console Application.

2 – Conditionally run as console or as a service based on a command line argument

Check for the “/CONSOLE” command line argument to determine if you need to run as a service or as a console app.

If you are running as a service, the framework will call TestService.OnStart(), and then you’ll call TestService.StartService(). If you’re running as a console app you’ll call TestService.StartService(). In both cases you’ll end up calling the StartService() method.

using System; using System.Linq; using System.ServiceProcess; namespace WindowsServiceAsConsole { static class Program { public static void Main(string[] args) { if (args.FirstOrDefault()?.ToUpper() == "/CONSOLE") { RunAsConsole(); } else { RunAsService(); } } private static void RunAsConsole() { TestService serv = new TestService(); serv.StartService(); Console.WriteLine("Running service as console. Press any key to stop."); Console.ReadKey(); serv.Stop(); } private static void RunAsService() { /* Warning: Don't load the object graph or * initialize anything in here. * * Initialize everything in TestService.StartService() instead */ ServiceBase[] ServicesToRun; ServicesToRun = new ServiceBase[] { new TestService() }; ServiceBase.Run(ServicesToRun); } } }
Code language: C# (cs)

3 – Add StartService() to the service class

The key here is to create a method that is called by both the service and console app. The framework will call OnStart() when starting as a service. It’s important that all you do is call StartService() in a new thread here.

Note: Avoid doing any initialization in OnStart(). Windows enforces a “startup time” for services, and your service will not finish starting up if it’s taking too long in OnStart().

using System; using System.ServiceProcess; namespace WindowsServiceAsConsole { public partial class TestService : ServiceBase { public TestService() { InitializeComponent(); } protected override void OnStart(string[] args) { new System.Threading.Thread(StartService).Start(); } protected override void OnStop() { } internal void StartService() { /* This is the true composition root for a service, so initialize everything in here */ Console.WriteLine("Starting service"); } } }
Code language: C# (cs)

4 – Add the /CONSOLE command line argument in the build options

To automatically run as a console app every time you start the program from Visual Studio, you can add the /CONSOLE flag as a command line argument. You should only do this for the Debug build configuration.

Make sure you’re not passing in /CONSOLE for the Release build configuration, otherwise when you deploy it’ll run as a console app in production.

Note: You can still run this as console app in production manually. Just open a command line and execute your exe with the /CONSOLE command line argument, like this:

Leave a Comment