Developing Windows Services

Windows Services are long-running processes that typically run in the background, independent of any user interaction. They are fundamental to the operation of many applications and system components, providing functionalities such as network access, database management, and application scheduling. This article provides a comprehensive guide to developing Windows Services using the .NET Framework.

What is a Windows Service?

A Windows Service is an executable file that can be started, stopped, and managed by the Windows Service Control Manager (SCM). Unlike regular applications that require a user to launch them, services can start automatically when the system boots up and continue running even when no user is logged in.

Key Concepts

  • ServiceBase: The abstract base class in the .NET Framework for creating Windows Services.
  • ServiceInstaller: A class used to install and configure the service on the system.
  • ServiceProcessInstaller: A class used to configure the account under which the service will run.
  • Service Control Manager (SCM): The system component responsible for managing services.

Getting Started: A Simple Service

Let's create a basic "Hello World" service that logs a message to the Windows Event Log.

1. Create a New Project

In Visual Studio, create a new project using the "Windows Service (.NET Framework)" template.

2. Implement the Service Logic

Open the code file for your service (e.g., Service1.cs). Inherit from ServiceBase and override the OnStart and OnStop methods.


using System;
using System.ServiceProcess;
using System.Timers;
using System.Diagnostics;

public class MyWindowsService : ServiceBase
{
    private Timer serviceTimer;
    private EventLog eventLog;

    public MyWindowsService()
    {
        // Configure Event Log
        eventLog = new EventLog();
        if (!EventLog.SourceExists("MyServiceSource"))
        {
            EventLog.CreateEventSource("MyServiceSource", "Application");
        }
        eventLog.Source = "MyServiceSource";
        eventLog.Log = "Application";
    }

    protected override void OnStart(string[] args)
    {
        eventLog.WriteEntry("MyWindowsService started.");

        // Set up a timer to do something every 60 seconds
        serviceTimer = new Timer();
        serviceTimer.Interval = 60000; // 60 seconds
        serviceTimer.Elapsed += new ElapsedEventHandler(ServiceTimer_Elapsed);
        serviceTimer.AutoReset = true;
        serviceTimer.Enabled = true;
    }

    protected override void OnStop()
    {
        eventLog.WriteEntry("MyWindowsService stopped.");
        serviceTimer.Stop();
        serviceTimer.Dispose();
    }

    private void ServiceTimer_Elapsed(object sender, ElapsedEventArgs e)
    {
        eventLog.WriteEntry("Service tick at: " + DateTime.Now.ToString());
    }

    // The main entry point for the service
    public static void Main()
    {
        ServiceBase.Run(new MyWindowsService());
    }
}
                    

3. Add Installers

Right-click on the project in Solution Explorer and select "Add" -> "New Item...". Choose "Installer Class" and name it (e.g., ProjectInstaller.cs). In the designer for the installer class, add two components from the toolbox:

  • ServiceProcessInstaller: Configure the account (e.g., LocalSystem, NetworkService).
  • ServiceInstaller: Configure the service name and display name.

using System;
using System.Collections;
using System.ComponentModel;
using System.Configuration.Install;
using System.ServiceProcess;

[RunInstaller(true)]
public class ProjectInstaller : Installer
{
    private ServiceProcessInstaller serviceProcessInstaller;
    private ServiceInstaller serviceInstaller;

    public ProjectInstaller()
    {
        // Initialize installers
        serviceProcessInstaller = new ServiceProcessInstaller();
        serviceInstaller = new ServiceInstaller();

        // Configure ServiceProcessInstaller
        serviceProcessInstaller.Account = ServiceAccount.LocalSystem; // Or NetworkService, LocalService

        // Configure ServiceInstaller
        serviceInstaller.ServiceName = "MyWindowsService"; // Must match ServiceBase.ServiceName
        serviceInstaller.DisplayName = "My Custom Windows Service";
        serviceInstaller.Description = "A sample Windows Service for demonstration.";
        serviceInstaller.StartType = ServiceStartMode.Automatic; // Or Manual, Disabled

        // Add installers to the collection
        Installers.AddRange(new Installer[] {
            serviceProcessInstaller,
            serviceInstaller });
    }
}
                    

Installing and Managing the Service

To install the service, open a Developer Command Prompt for Visual Studio as an administrator. Navigate to your project's output directory (e.g., bin\Debug or bin\Release) and run:

installutil YourServiceName.exe

To uninstall the service:

installutil /u YourServiceName.exe

You can then manage the service through the "Services" application in Windows (services.msc).

Important Note:

When developing services, ensure you handle exceptions gracefully and log errors to the Event Log or a dedicated log file. This is crucial for debugging and troubleshooting.

Advanced Topics

  • Service Recovery: Configure what happens if the service fails (e.g., restart).
  • Interacting with Services: Use ServiceController class to programmatically start, stop, or query service status.
  • Security: Carefully choose the service account based on the permissions required.
  • WCF and Web Services: Services can host WCF endpoints or expose web services for client communication.

Developing robust Windows Services requires attention to detail, particularly regarding error handling, resource management, and security. By following these guidelines and leveraging the .NET Framework's service development tools, you can build reliable background processes for your applications.