When I work with Engineers who are developing Windows Services, or perform code reviews of already existing Services, I see that people have a hard time working with and debugging Windows Services.
Frequently I see people stuff code into DLL’s then create two projects that consume the Class Library – a Console Application for debugging and a Windows Service for production use.
While stuffing code into class libraries is often a good idea, creating an extra project usually isn’t. Fortunately there’s a better way: The hybrid service.
Let’s start by creating a standard Windows Service in C#. To this I’m going to add a worker thread and a shutdown event – pretty much every service ever written does this, so there’s certainly nothing new here. I’m also going to create a pair of Public methods to startup and shutdown the service. The use for these will become clear here shortly.
public partial class Service1 : ServiceBase
{
private Thread _myThread;
private ManualResetEvent _shutdown = new ManualResetEvent(false);
public Service1() : base()
{
InitializeComponent();
}
protected override void OnStart(string[] args) { StartMeUp(); }
protected override void OnStop() { ShutMeDown(); }
public void StartMeUp()
{
_shutdown.Reset();
_myThread = new Thread(new ThreadStart(DoSomething));
_myThread.Start();
}
public void ShutMeDown()
{
_shutdown.Set();
_myThread.Join();
}
private void DoSomething()
{
while (_shutdown.WaitOne(5000, false) == false)
System.Diagnostics.Debug.WriteLine("Doing Work");
}
}
Now things are going to get a bit tricky. In the Main() portion of the program, I’m going to check for a “-debug” command line argument, and if that’s there I’m going to assume that we’re running as a Console application, and just use the Service class as if I were in a Console App. Those public Startup/Shutdown methods you saw in the Service itself are used here to startup and shutdown the Service. There are, I’m sure, a number of better ways to do this but this one seems to work and, hey, it’s just Debug code… J
Notice that if there’s no “-debug” passed in, that normal Service Startup happens.
static class Program
{
static void Main()
{
if (System.Environment.CommandLine.ToLower().Contains("-debug"))
{
Console.WriteLine("Starting Service in Debug");
using (Service1 debugService = new Service1())
{
debugService.StartMeUp();
Console.WriteLine("Service Started. Press 'Enter' to Exit");
Console.ReadLine();
debugService.ShutMeDown();
}
}
else
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[] { new Service1() };
ServiceBase.Run(ServicesToRun);
}
}
}
Once you have this code written, you should go into the "Debug" section of the project settings and add "-debug" to the command line arguments. This way each time you run under the debugger, your app will run just like you intend it to. This means very simple debugging for the vast majority of your code.
Lastly, you need to set the Project Type of the application to be a Console Application. This is done in the project properties.

This technique of making an application both a Console Application and a Windows Service works our pretty well. An entire project is eliminated from your build tree, and you end up debugging on code that is pretty close to the final production code. You can also play this same trick with a WinForms application and a Windows Service – everything works pretty much the same way.
You can find the source code at our download site.