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:
- Install the Windows Service and look at the logs. This is tedious and slows down development.
- 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:
awesome !!! how to came to think it like this.