wolfgang ziegler


„make stuff and blog about it“

Creating and Debugging a C# Windows Service

June 4, 2014

One of my recent projects - WhatsMyIP - also required me writing a Windows Service.

That's when I realized that even tough being a .NET developer for more than 10 years now, I have never written a managed Windows Service until now.

But since Visual Studio has a built-in service project template for ages now, of course I built this service using C# and .NET.

New Windows Service Project

Having created the boiler-plate service project, I tried what I usually do as a first step and ran it in the debugger. Interestingly, I ended up, getting this error message.

 Windows Service Start Failure

It turns out that debugging a managed Windows Service is not that straightforward, what actually makes a lot of sense, since services usually run in their own session and isolated from the user.

One does not(?) simply debug a Windows Service

But it turns out, with a few simple tricks and adaptions it actually is quite simple to debug a Service class and run it as a user process.

Code Changes

By checking whether we are running in interactive mode (Environment.UserInteractive), we can determine dynamically whether we are running as a service or as a user process.

In the first case the code stays the same as before, but in the second case, we manually invoke a Start method (which we have to add to our service class) and then call Stop on the service again.

Here's the code.

static class Program
{
  static void Main()
  {
    var serviceToRun = new MyIpService();
    if (Environment.UserInteractive)
    {
      serviceToRun.Start();
      Console.WriteLine("... press <ENTER> to quit");
      Console.ReadLine();
      serviceToRun.Stop();
    }
    else
    {
      ServiceBase.Run(serviceToRun);
    }
  }
}

public partial class MyService : ServiceBase
{
  public MyService()
  {
    InitializeComponent();
  }

  //
  // This is the method we manually added.
  //
  internal void Start()
  {
    OnStart(null);
  }

  protected override void OnStart()
  {
     // Your start logic here.
  }

  protected override void OnStop()
  {
     // Your stop logic here.
  }
}

Project Type

We also have to make our application a Console Application instead of a Windows Application, otherwise the Console.ReadLine command will return immediately and thus stop our service, which is probably not the intended behavior.

Console Application

Add an Installer

As we can successfully debug the Start and Stop mechanisms of our service, we can now prepare it for its actual deployment.
For that, we need to add an Installer Component to the Service so Windows knows how to register it correctly. The easiest way to do that is by right clicking the design view of your Service class and using the context menu entry "Add Installer".

Add Installer

This will give us a new class ProjectInstaller, for which we can specify a couple of properties, most importantly the user account under which it will run and its startup behavior (Manual / Automatic / Disable).

Installer Properties

Deploying

Finally we can deploy our service. This happens through a tool called installutil.exe.

installutil.exe WhatsMyIP.Service.exe

Make sure though you use an elevated Developer Command Prompt for that.

And that's all we need to do - the new service is registered and running!

The new service in Service Manager

.NET and C# FTW!