Skip to main content

...

....

C# - Creating a Simple Windows Service [Beginner]


We all know what a WindowsService is - a long running executable that's designed to work without user interaction. They can be configured to start when the system boots and they can be run without any users logged into the system. This tutorial is going to provide step-by-step instructions on how to build a Windows Service using C# and .NET.

The first thing you're going to want to do is create a new Console Application in Visual Studio. I like to start building services as console applications so they can easily be tested and debugged before converting them to services.

New Console Application
Dialog

In order to build services, we depend on some .NET objects location in the System.ServiceProcess and System.Configuration.Install assemblies. Go ahead and add those references to your project.

Visual Studio Project
References

When you created the project, Visual Studio should have created a file called Program.cs, which looks something like this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MyWindowsService
{
  class Program
  {
    static void Main(string[] args)
    {
    }
  }
}
 
The only thing we need to do in order to make this class into a service is make Program extend System.ServiceProcess.ServiceBase.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceProcess;

namespace MyWindowsService
{
  class Program : ServiceBase
  {
    static void Main(string[] args)
    {
    }
  }
}
 
By extending ServiceBase, we're given a bunch of service related functions we can override. At a minimum, every service should override OnStart and OnStop. These are where, as the names imply, your custom logic should go when the service is started and stopped.
class Program : ServiceBase
{
  static void Main(string[] args)
  {
  }

  protected override void OnStart(string[] args)
  {
    base.OnStart(args);

    //TODO: place your start code here
  }

  protected override void OnStop()
  {
    base.OnStop();

    //TODO: clean up any variables and stop any threads
  }
}
 
There are several other functions beyond start and stop like pause, continue, and shutdown, but they're not needed for a basic service. For all available functions, check out the ServiceBase memberlist on MSDN.

Now we need to add some information about our service - like a name. Let's add a constructor to Program and put it there.
class Program : ServiceBase
{
  static void Main(string[] args)
  {
  }

  public Program()
  {
    this.ServiceName = "My Service";
  }

  protected override void OnStart(string[] args)
  {
    base.OnStart(args);

    //TODO: place your start code here
  }

  protected override void OnStop()
  {
    base.OnStop();

    //TODO: clean up any variables and stop any threads
  }
}
 
The constructor is where you'd also set lots of other information about your service (if the default settings wouldn't work). These can include things like which events it can handle, what operation it can do (pause, stop, etc.), and what event log it should log information to (application, system, etc.). For us, however, the default settings will work just fine.

We're very close to having a finished service. All that left is to tell Windows what service to run when your application it executed. Just like normal applications, execution begins in the Main function. This is where we'll create an instance of our service and tell it to run.
class Program : ServiceBase
{
  static void Main(string[] args)
  {
    ServiceBase.Run(new Program());
  }

  public Program()
  {
    this.ServiceName = "My Service";
  }

  protected override void OnStart(string[] args)
  {
    base.OnStart(args);

    //TODO: place your start code here
  }

  protected override void OnStop()
  {
    base.OnStop();

    //TODO: clean up any variables and stop any threads
  }
}
 
That's it! The service implementation is complete. We can't install it yet though, because we haven't implemented an installer. To do that we need to add another class to our project called MyWindowsServiceInstaller.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MyWindowsService
{
  class MyWindowsServiceInstaller
  {
  }
}
 
When Visual Studio creates a class for you, it doesn't automatically make it public. It's very important that this class be made public. When you install a service, the installer will look through your assembly for public classes with a specific attribute. If it's not public, it won't find it.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MyWindowsService
{
  public class MyWindowsServiceInstaller
  {
  }
}
 
This class needs to extend System.Configuration.Install.Installer and be given a RunInstaller attribute. This is the attribute that the service installer looks for when installing your service.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration.Install;
using System.ComponentModel;

namespace MyWindowsService
{
  [RunInstaller(true)]
  public class MyWindowsServiceInstaller : Installer
  {
  }
}
 
Now we need to configure how we want our service installed. We'll do this in the constructor for the class we just created.
[RunInstaller(true)]
public class MyWindowsServiceInstaller : Installer
{
  public MyWindowsServiceInstaller()
  {
    var processInstaller = new ServiceProcessInstaller();
    var serviceInstaller = new ServiceInstaller();

    //set the privileges
    processInstaller.Account = ServiceAccount.LocalSystem;

    serviceInstaller.DisplayName = "My Service";
    serviceInstaller.StartType = ServiceStartMode.Manual;

    //must be the same as what was set in Program's constructor
    serviceInstaller.ServiceName = "My Service";

    this.Installers.Add(processInstaller);
    this.Installers.Add(serviceInstaller);
  }
}
 
This is pretty much the bare minimum when it comes to service options. We have to create a ServiceProcessInstaller and a ServiceInstaller. These two classes are responsible for installing the service. The ServiceProcessInstaller installs information common to all services, and the ServiceInstaller installs information for this specific service.

The Account property sets which privileges you'd like the service to run under. The default is User, but then we'd have to specify a username and a password to determine the account. I chose LocalSystem, which gives the service a lot (probably too much) access to the local computer.

Services are identified by name, so you have to ensure serviceInstaller.ServiceName is exactly the same as what you set in the constructor of Program. The rest of the options are pretty obvious. All that's left is to add our two installers to the Installers collection.

We're done! All that's left to do now is install the service.

 

Installing The Service

Services are installed using a tool from Microsoft called installutil.exe. This tool is free and is probably already on your computer. I doubt it's in your system path, so you might want to do a quick search for it and add it to your environment variables before continuing.

All you have to do to install your service is open a command prompt, cd to your Release directory, and type:
installutil MyWindowsService.exe
 
installutil
output

Your service is now installed and ready to go. If you bring up your services manager, you should see one labeled "My Service". Of course, if you start it, nothing will happen since we didn't actually put any code in the OnStart function.

Windows Service
List

If you want to uninstall the service, you can do so with the same utility but with the "-u" flag.
installutil -u MyWindowsService.exe
 
There's a lot of power that we haven't even touched in Windows Services, but this tutorial should hopefully give you a starting point on which you can expand and build some much more complex solutions. All of the example code has been attached as a Visual Studio 2008 solution.

Source Files:

Comments

Popular posts from this blog

C# Snippet - Shuffling a Dictionary [Beginner]

Randomizing something can be a daunting task, especially with all the algorithms out there. However, sometimes you just need to shuffle things up, in a simple, yet effective manner. Today we are going to take a quick look at an easy and simple way to randomize a dictionary, which is most likely something that you may be using in a complex application. The tricky thing about ordering dictionaries is that...well they are not ordered to begin with. Typically they are a chaotic collection of key/value pairs. There is no first element or last element, just elements. This is why it is a little tricky to randomize them. Before we get started, we need to build a quick dictionary. For this tutorial, we will be doing an extremely simple string/int dictionary, but rest assured the steps we take can be used for any kind of dictionary you can come up with, no matter what object types you use. Dictionary < String , int > origin = new Dictionary < string , int >();

C# WPF Printing Part 2 - Pagination [Intermediate]

About two weeks ago, we had a tutorial here at SOTC on the basics of printing in WPF . It covered the standard stuff, like popping the print dialog, and what you needed to do to print visuals (both created in XAML and on the fly). But really, that's barely scratching the surface - any decent printing system in pretty much any application needs to be able to do a lot more than that. So today, we are going to take one more baby step forward into the world of printing - we are going to take a look at pagination. The main class that we will need to do pagination is the DocumentPaginator . I mentioned this class very briefly in the previous tutorial, but only in the context of the printing methods on PrintDialog , PrintVisual (which we focused on last time) and PrintDocument (which we will be focusing on today). This PrintDocument function takes a DocumentPaginator to print - and this is why we need to create one. Unfortunately, making a DocumentPaginator is not as easy as

C# WPF Tutorial - Implementing IScrollInfo [Advanced]

The ScrollViewer in WPF is pretty handy (and quite flexible) - especially when compared to what you had to work with in WinForms ( ScrollableControl ). 98% of the time, I can make the ScrollViewer do what I need it to for the given situation. Those other 2 percent, though, can get kind of hairy. Fortunately, WPF provides the IScrollInfo interface - which is what we will be talking about today. So what is IScrollInfo ? Well, it is a way to take over the logic behind scrolling, while still maintaining the look and feel of the standard ScrollViewer . Now, first off, why in the world would we want to do that? To answer that question, I'm going to take a an example from a tutorial that is over a year old now - Creating a Custom Panel Control . In that tutorial, we created our own custom WPF panel (that animated!). One of the issues with that panel though (and the WPF WrapPanel in general) is that you have to disable the horizontal scrollbar if you put the panel in a ScrollV