Create a Windows Service

This is part of a series on creating and installing Windows services.

  1. How to Create a Windows Service
  2. How to Install a Windows Service
  3. How to Run a Windows Service from Visual Studio
  4. How to Avoid Windows Service Start-up Timeouts
  5. How to Make a Windows Service Install Itself
  6. How to Handle Windows Service Errors
  7. How to Build a Windows Service Framework

Windows services are a very simple yet powerful feature of our platform of choice. A Windows service is an application that can run in the background, managed by an operating system component called the Service Control Manager. Services can be started and stopped on command (via services.msc or a number of other utilities), making them the ideal platform for “server” programs that need to run indefinitely. This article begins a series on working with Windows services in code. Our goal is to get you familiar with creating, installing, and running Windows services while building reusable components that will make it simple to build consistent and reliable services.

In this article, we will create a basic Windows service without relying on Visual Studio’s templates. While the templates allow you to get up and running quickly, they over-complicate the mechanics of running and installing a Windows service, and they discourage the creation of reusable components (as do all code “templates”). Those of you using VS Express will notice that the Windows service templates are not available to you at all — and by the end of this article, you’ll learn how little you’re missing.

To start, create a console application in Visual Studio (I will call mine “DemoService”). Add a reference to “System.ServiceProcess.dll”, which is not included by default. This assembly contains all the classes needed to interact with Windows services, most importantly System.ServiceProcess.ServiceBase. Next, alter your Program.cs thusly:

class Program
{
    static void Main(string[] args)
    {
        ServiceBase.Run(new MyService());
    }
}

class MyService : ServiceBase
{
}

You will need to import System.ServiceProcess to prevent the compiler from whining about the reference to “ServiceBase”. This is the bare minimum code necessary to get the Service Control Manager to run a service. When we call ServiceBase.Run, we basically hand control over to the Service Control Manager, allowing it to handle the provided service implementation (MyService) as it sees fit. The base class, ServiceBase, gives your derived class access to the “events” associated with the service’s lifecycle via its virtual methods, such as OnStart and OnStop. We will fill those methods out later, but for now we will just use the default functionality to get up and running.

If you “run” the application from Visual Studio, you’ll notice this lovely little dialog box:

NoServicesFromConsole

The dialog is telling us that we are trying to run a windows service in the console, which doesn’t make sense, because Windows services can only be run by the Service Control Manager. To make that happen, we must fire up the command line (as an administrator on Vista and greater). We will “install” our service using the sc command, which is a multi-function utility for managing Windows services (run sc /? for help). Execute the following command to install the service:

sc create DemoService c:\full\path\to\DemoService.exe

The first parameter to sc create is the name of the service, and the second is the absolute path to the executable containing the service (sc create will still succeed if you provide a relative path, but the service will fail to run). Upon successful service creation, you should see the following output:

[SC] CreateService SUCCESS

Now that the service is successfully registered with the Service Control Manager, we can actually run it. From the “run box” (Win+R), launch “services.msc” to access the services console. You should be able to find “DemoService” in the grid on the right:

servicesmmc

To start the service, do one of the following:

  • Click the “Start the service” link next to the grid
  • Click the green “play” button in the toolbar
  • Right-click the service’s row in the grid and select “Start” from the context menu
  • Select “Action->Start” in the menu bar

You will see the following dialog while the service is starting:

servicestart

After the service starts, you should see “Started” in the “Status” column of the services.msc grid. To stop the service:

  • Click the “Stop the service” link next to the grid
  • Click the black “stop” button in the toolbar
  • Right-click the service’s row in the grid and select “Stop” from the context menu
  • Select “Action->Stop” in the menu bar

While stopping, you will see a dialog similar to the start-up dialog:

servicestop

We can view the history of our service starting and stopping by using the Event Viewer. Launch “eventvwr” from the “run box”, and under “Windows Logs”, select “System”. You should see an event from the “Service Control Manager” each time you started or stopped your windows service:

serviceevents

There will also be an event from the “Service Control Manager” marking the installation of the service. It will contain the message “A service was installed in the system” and include the name of the service.

There you have it! All you need to get a basic Windows service running is one line of code and a basic command-line utility. No templates, no bells, no whistles. Unfortunately, our service doesn’t really do anything useful. But we can work on that next time.

 
Comments

https://github.com/kohsuke/winsw is also a handy tool if you have a command line utility that you want to run as a service.

That looks interesting, thanks for the tip! One of the things I’m hoping to prove with this article (and the forthcoming series on this topic) is that it’s not hard to create windows services. If we build a little bit of infrastructure, it can be just as trivial to create a service as it is to create a console app.

On my Surface 3 (Windows 8.1), I had to use this syntax to install the service:
sc create DemoService binPath=”c:\full\path\to\DemoService.exe”

Also, although installing the service was logged in the EventViewer, starting and stopping of the service was not. I’m guessing that you can configure things to make that happen, but mine is a brand new computer, so it looks like the default is to not log service starts and stops to the EventViewer.

I had to use binpath= before the full path to executable to get the service created. without it didnt create the service. The syntax might have changed in these 2 years

sc create DemoService binPath= ”c:\full\path\to\DemoService.exe”

Trackbacks for this post

Leave a Reply