.netCoders Contact Us
Search:

Windows Services

With the .NET Framework, it is much easier to develop applications that run as Windows Services using classes defined in the System.ServiceProcess namespace. This article starts with an overview of the ServiceProcess namespace and the classes you are most likely to use in developing your own services. Next, we'll look at an developing an example using Visual Studio.NET. Finally, we'll cover the installation of your service.

System.ServiceProcess Namespace

From the System.ServiceProcess namespace, there is one key base class in developing services, two used in deploying services, and one key class used for managing services. They are:

ServiceBase - this is the base class for Windows Services. Your class will derive directly or indirectly from this class. For your service to be useful, you'll override the OnStart, OnPause, and OnStop methods.

ServiceProcessInstaller - this class is involved in installing your service with the Service Control Manager, and does work common to all services in an executable such as writing registry values associated with your services. You will need one instance of this class per application.

ServiceInstaller - this class is also involved in installying your service, and writes registry information for a particular service. You need a separate ServiceInstaller for each service in your application.

ServiceController - this class gives you programmatic access for connecting to a service, manipulating it, and get information about it. Using this class, you can start or stop services from a custom application.

Creating a Windows Service

To create a Windows Service in Visual Studio.NET, create a New Project and select the Windows Service project type in the New Project dialog. Visual Studio will create a skeleton service for you called Service1, derived from ServiceBase. When the process is complete, Visual Studio will be loaded with your service in Design View.

Next, click on the link that says "click here to switch to code view", or right click in design view and select View Code from the context menu. Find the OnStart method, which is called when your service is started. Here is where you would add your custom logic. For our example, we are going to leave the service as is, since by default the service will write to the Event Log whenever it is started or stopped. That will be enough to verify that our service is working. Below is the code for our service.

There are three things to note. First is the constructor, where you can add your custom initialization code. Next is the OnStart and OnStop methods, which is where you can add your custom service behavior. Third is the Main method. In order to run your service, this method must pass an instance of your method to the ServiceBase.Run static method.

using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.ServiceProcess;

namespace DotnetCodersMailService
{
    public class Service1 : System.ServiceProcess.ServiceBase
    {
        private System.ComponentModel.Container components = null;

        public Service1()
        {
            // This call is required by the Windows.Forms Component Designer.
            InitializeComponent();

            // TODO: Add any initialization after the InitComponent call
        }

        // The main entry point for the process
        static void Main()
        {
            // More than one user Service may run within the same process. To add
            // another service to this process, change the following line to
            // create a second service object. For example,
            // ServicesToRun = New System.ServiceProcess.ServiceBase[] {new Service1(), new MySecondUserService()};

            System.ServiceProcess.ServiceBase[] ServicesToRun;
            ServicesToRun = new System.ServiceProcess.ServiceBase[] { new Service1() };
            System.ServiceProcess.ServiceBase.Run(ServicesToRun);
        }

        private void InitializeComponent()
        {
            components = new System.ComponentModel.Container();
            this.ServiceName = "Service1";
        }

        protected override void Dispose( bool disposing )
        {
            if( disposing )
            {
                if (components != null)
                {
                    components.Dispose();
                }
            }
            base.Dispose( disposing );
        }

        protected override void OnStart(string[] args)
        {
            // TODO: Add code here to start your service.
        }

        protected override void OnStop()
        {
            // TODO: Add code here to perform any tear-down necessary to stop your service.
        }
    }
}

Adding a Windows Service Installer

Once you have the code for your service ready, return to Design mode, right click, and select Properties. Change the name property if you want, which is the name of your class. Next, change the ServiceName property, which is the name used when displaying your service in the Service Control Manager, and used to identify your service by the Installers.

Note: If you change the name of your class, you may also need to change it in the Main() method of your service. Visual Studio does not automatically update the service name. Look for a line like the following, and change Service1 to the new name of your service class.
ServicesToRun = new System.ServiceProcess.ServiceBase[] { new Service1() };

Next we'll add the necessary Installers for our service. At the bottom of the Properties menu, you will see a link for Add Installer. By clicking this, Visual Studio will do some work and will finish in Design mode for a new file, ProjectInstaller.cs. You'll notice the class contains a ServiceProcessInstaller, and a ServiceInstaller. Right click in the design pane and select View Code to see the code in this file.
Visual Studio has created a ProjectInstaller class deriving from System.Configuration.Install.Installer, which contains an instance of a ServiceProcessInstaller and a ServiceInstaller. Expand the "Component Designer generated code" to see that these two components have been added to the Installers collection. This will ensure that our installer classes are called to install our service when we use the InstallUtil.exe command line utility.

Return to Design mode for the ProjectInstaller class. Right click on the serviceProcessInstaller1 icon, and select Properties. In the properties window, change the Account property to LocalSystem. This is who the service is set to run as when you install your service. If you leave it as User, the install program will prompt you for a username and password. Setting this value to LocalSystem will make installation a little easier, since we will not have to indicate a specific user account under which to run the service.

Build your project, and now you are ready for deployment.

Installing the Service

To install your service, you first need to Build it from Visual Studio.NET. This will create an .exe file in the bin/debug directory. Next, you need to use the InstallUtil.exe command line utility. The syntax for this utility is as follows:
InstallUtil.exe [ServiceExeFile]
Open a command console and navigate to the bin/debug directory under your Visual Studio.NET project. Once there, run InstallUtil using the syntax above. In our example, we'll run:
InstallUtil DotnetCodersMailService.exe
The following screen show shows you what you can expect for output if the installation was successful:

Managing the Service

Once your service is installed, you can control it from the Windows Services ControlManager (Programs->AdministrativeTools->Services). The following screenshot shows our service, and indicates that it is not currently started, has to be started manually, and runs under the LocalSystem account.
You can also control your service programmatically with the ServiceController class. This allows you to incorporate the tracking of and the changing of your service's state (start, paused, stopped). Using this class will be covered in a future article.

Click your service and select Start. Now, check your machine's Application Event Log. You'll see an Information event noting that your service has started!