Working with Windows Services in .NET
 
Published: 05 Dec 2006
Abstract
Windows Services are long running applications in Windows environments. This article discusses what Windows Services are and the ways to create, install and deploy them in .NET
by Joydip Kanjilal
Feedback
Average Rating: 
Views (Total / Last 10 Days): 75392/ 119

Introduction

Windows Services are long running executable applications that have no User Interface, can be configured to start automatically and can also be started manually.  Windows services are not meant to interact with users and should not have a user interface.  These applications are actually controlled by the Service Control Manager.  This article discusses Windows Services and shows how we can implement a simple Windows Service in C#.

What are Windows Services?

Windows services are long running executable applications that typically do not possess any user interface, are controlled by the Service Control Manager (SCM) and can even be configured to start automatically after the system boots.  They typically execute in their own windows sessions. They can execute even if the user has not logged in to the system.  They can even be started, paused, re-started manually.  These applications are somewhat similar to the daemon processes of UNIX in the sense that they remain dormant most of the time and execute in the background as and when needed.

Why are Windows Services needed?

The following are the benefits of using Windows Services:

·         Network connection management

·         Disk access monitoring

·         Security control of application

·         Log messages related to the application's requirements

Anatomy of a Windows Service Application

This section briefly discusses the anatomy of a Windows Service application.  The .NET Framework's System.ServiceProcess.ServiceBase encapsulates the entire functionality that is required to create and control Windows Service applications.

The following two classes are required for implementing a Windows Service:

·         System.ServiceProcess.ServiceBase

·         System.Configuration.Install.Installer

The ServiceBase class must be inherited by your Service class to specify your Service and the Installer class should be inherited in your Installer class to specify the Service installer.

The following are the methods of ServiceBase class.

·         OnStart

·         OnStop

·         OnPause

·         OnContinue

·         OnShutdown

·         OnPowerEvent

·         OnCustomCommand

The following section discusses these methods briefly.

OnStart: This method is fired when the service is started by the Service Control Manager.  It should be noted that this method is called only once during the life cycle.  This method is used to specify the processing that occurs when a Start command is received.

OnStop: This method is called when the service is stopped by the Service Control Manager.  This is typically used to specify the processing that occurs when a Stop command is received by the Service Control Manager.

OnPause: This method is called when the service is paused and typically contains the processing for pausing the service.

OnContinue: This method is called when the service is resumed after being paused.  This method typically contains the necessary processing so as to enable a service to return to normal functioning after the same was paused earlier.

OnShutDown: This method is called when the system is being shutdown and contains the necessary processing indicative of what should happen prior to the system shutting down.

OnPowerEvent: This method is used to specify the necessary processing that should take place when the power status changes.

OnCustomCommand: This method is used to specify a custom command, i.e., any command other than those discussed above.

In addition to the above methods, the System.ServiceProcess.ServiceBase class also contains the following properties:

·         AutoLog

·         CanPauseAndContinue

·         CanShutdown

·         CanStop

·         ServiceName

The following section discusses these properties briefly.

CanStop: This is a boolean property that is true if the service can be stopped, false otherwise.

CanShutdown: This is a boolean property that is true if the service wants to be notified that the system on which it is being executed is being shutdown, false otherwise.

CanPauseAndContinue: This is a boolean property that is true if the service can be paused and then restarted, false otherwise.

CanHandlePowerEvent: This is a boolean property that is set to true if the service should be notified of a change in the power status of the system on which the service is being executed.

AutoLog: This is a boolean property that is set to true if the service should write events to the Application Event Log when any action is performed.

Implementing a Simple Windows Service Application in .NET

This section makes use of the concepts learned so far and shows how we can implement a simple Windows Service in .NET.

Creating the Windows Service

To create a new project in Visual Studio .NET 2003, select C# as the language of your choice and then select Windows Service as the project.  Specify the name of the project and save the same. Note that when implementing a Windows Service, you should have two classes, one is the Service class and the other is the Service Controller class.  Refer to the following listings that contain the source code for both the custom Service and the custom ServiceController classes.

Listing 1: The Sample Windows Service Class

using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.ServiceProcess;
using System.IO;
 
namespace SampleWindowsService
{
  public class SampleWindowsService: System.ServiceProcess.ServiceBase
  {
    StreamWriter streamWriter;
    private System.ComponentModel.Container components = null;
    public SampleWindowsService()
    {
      InitializeComponent();
    }
 
    static void Main()
    {
      System.ServiceProcess.ServiceBase[]ServicesToRun;
      ServicesToRun = new System.ServiceProcess.ServiceBase[]
      {
        new SampleWindowsService()
      };
      System.ServiceProcess.ServiceBase.Run(ServicesToRun);
    }
 
 
    private void InitializeComponent()
    {
      components = new System.ComponentModel.Container();
      this.ServiceName = "Sample Service";
    }
 
 
    protected override void Dispose(bool disposing)
    {
      if (disposing)
      {
        if (components != null)
        {
          components.Dispose();
        }
      }
      base.Dispose(disposing);
    }
 
    protected override void OnStart(string[]args)
    {
      streamWriter = new StreamWriter(new FileStream(
        "C:\\SampleWindowsServiceLogger.txt", System.IO.FileMode.Append));
      this.streamWriter.WriteLine("Starting Sample Windows Service at " +
        DateTime.Now.ToString());
      this.streamWriter.Flush();
      this.streamWriter.Close();
    }
 
    protected override void OnStop()
    {
      streamWriter = new StreamWriter(new FileStream(
        "C:\\SampleWindowsServiceLogger.txt", System.IO.FileMode.Append));
      this.streamWriter.WriteLine("Stopping Sample Windows Service at " +
        DateTime.Now.ToString());
      this.streamWriter.Flush();
      this.streamWriter.Close();
    }
  }
}

Listing 2: The Sample Windows Service Installer Class

using System;
using System.Collections;
using System.ComponentModel;
using System.ServiceProcess;
using System.Configuration.Install;
 
namespace SampleWindowsService
{
  [RunInstaller(true)]
  public class SampleWindowsServiceInstaller:
    System.Configuration.Install.Installer
  {
 
    private System.ComponentModel.Container components = null;
 
    public SampleWindowsServiceInstaller()
    {
      InitializeComponent();
      ServiceProcessInstaller spi = new ServiceProcessInstaller();
      ServiceInstaller si = new ServiceInstaller();
      si.DisplayName = "Sample Windows Service";
      si.ServiceName = "Sample Windows Service";
      si.StartType = ServiceStartMode.Automatic;
      this.Installers.Add(si);
 
      spi.Account = ServiceAccount.LocalSystem;
      spi.Username = null;
      spi.Password = null;
      this.Installers.Add(spi);
    }
 
    protected override void Dispose(bool disposing)
    {
      if (disposing)
      {
        if (components != null)
        {
          components.Dispose();
        }
      }
      base.Dispose(disposing);
    }
    private void InitializeComponent()
    {
      components = new System.ComponentModel.Container();
    }
  }
}

The Windows Service implemented in this article stores the time of starting, stopping or resuming the service in a file C:\\SampleWindowsServiceLogger.txt in the local file system.  Make changes to implement the service that can suit your needs.

Start, stop and resume the Windows Service

Go to Control Panel | Administrative Tools | Computer Management and select the Services and Applications tab.  Then locate your installed service and click on Start to start the service.  The rest is self explanatory.

Installing the Windows Service

In order to install the Windows Service implemented above, use the installutil .NET Framework command line utility.  Specify the following at the command prompt.

Installutil SampleWindowsServiceInstaller.exe

Un-Installing the Windows Service

In order to uninstall the Windows service, specify the following at the command prompt:

Installutil /u SampleWindowsServiceInstaller.exe
Important Points

You should note that a Microsoft .NET service will not start if the application event log is full. Hence, it is recommended to clear the event log down and set to overwrite as needed.  Remember inheriting the ServiceBase class to create you Service class and the System.Configuration.Install.Installer class when implementing your Service Controller class.

References

Conclusion

Windows services are powerful applications that need not have any user interface and can execute in the background to perform a lot of activities related to monitoring your system or writing necessary data to a log periodically.  It can be controlled manually as well as configured to be invoked automatically when the system starts up.  This article has provided a detailed know how on Windows Services and illustrated how we can implement a simple Windows Service in .NET.



User Comments

Title: Mr   
Name: Gautam Sharma
Date: 2007-01-02 5:48:04 AM
Comment:
This article is very nice.I run my first windows service and installed sucessfully.
Thanks
Title: Good article   
Name: Harinath
Date: 2006-12-20 12:50:50 AM
Comment:
I found this article really useful. thanks for the same
Title: .NETPhreak   
Name: Dhaval Patel
Date: 2006-12-07 1:51:32 AM
Comment:
It should be pointed out that the call to the OnStart() method should return back to the SCM (Service Control Manager) within 30 seconds (this value can be altered in the registry, but it is not always feasible to do so in a production environment). The best idea is to encapsulate all your functionality into a separate .dll within a method, say for example RequestStart(), that is spawned in a new thread. All that you would need then is to instantiate that .dll in OnStart() and call RequestStart() - since RequestStart() has all its functionality in a new thread, the call to OnStart() will return immediately to the SCM. Additionally, if you make this thread a background thread, every time you stop your service, the thread will also die; this way you may not need to provide any functionality in your OnStop() method.
Title: Great one...   
Name: Sandeep Acharya
Date: 2006-12-05 9:47:00 PM
Comment:
I had no hands on windows services till now and very soon I am going to start working on this for some urgent requirement. And I must say that this article will help me a lot. I could able to develope a dummy one by refering to this article.

Thanks for publishing such useful articles.
Title: Making it Easier   
Name: Ambrose
Date: 2006-12-05 3:44:22 PM
Comment:
Might want to also consider things that raise the abstraction level:
http://aspalliance.com/749_The_Perfect_Service__Part_1

Product Spotlight
Product Spotlight 





Community Advice: ASP | SQL | XML | Regular Expressions | Windows


©Copyright 1998-2017 ASPAlliance.com  |  Page Processed at 2017-10-22 2:54:24 PM  AspAlliance Recent Articles RSS Feed
About ASPAlliance | Newsgroups | Advertise | Authors | Email Lists | Feedback | Link To Us | Privacy | Search