Creating an Extensible Windows Service

By Robert Chartier

The first article in this series shows how to create a Windows Service that never needs modification and that allows system administrators and developers to develop and deploy custom plug-ins (although changing any of the plug-ins means stopping and restarting the service).

The second article covers actual plug-in development.

The code in this article is written with the aid of Visual Studio .NET (VS .NET), but it is not a requirement if you're familiar with the command line compilers that ship with the .NET Framework SDK.

Step One: Creating the Windows Service

The first step describes the process of setting up the actual Windows Service class. It will be based on a timer control, which has an interval set by the administrator via the configuration file.

Open up Visual Studio .NET (VS .NET) and create a New C# Windows Service.

Creating a New C# Windows Service in VS.NET.
Figure 1.1 - Creating a New C# Windows Service in VS.NET.

VS .NET will default to the designer for the Service. We won't need the designer for anything except changing the Service name. Change both "(Name)" and "ServiceName" to "scheduler". Also, switch to the "Solution Explorer", and rename the default file from "Service1.cs" to "Scheduler.cs".

By default VS .NET will implement a lot of code that is essential for the Service to execute normally. Notice that our Service class derives from the framework's "System.ServiceProcess.ServiceBase" class.

We must first implement a timer control to run our plug-in at given intervals.

1. Create a timer object at class scope:

private System.Timers.Timer timer=null;

2. Set up the timer within the class constructor:

public scheduler() {

string servicepollinterval = System.Configuration.ConfigurationSettings.AppSettings

	double interval=10000;
	try {
		interval = Convert.ToDouble(servicepollinterval);
	}catch(Exception) {}
timer = new System.Timers.Timer(interval);
	timer.Elapsed += new ElapsedEventHandler( this.ServiceTimer_Tick );


Notice that we are getting the timer's interval value by using


I will cover the configuration file in more detail in step three.

timer.Elapsed += new ElapsedEventHandler( this.ServiceTimer_Tick );

This sets up the event handler for when the timer elapses. It will be fired when the timer runs for the duration of the set interval. I'll get into more detail on this further down.

3. Next we need to start and stop the timer based on our Service's events.

protected override void OnStart(string[] args) {
	timer.AutoReset = true;

protected override void OnStop() {
	timer.AutoReset = false;
	timer.Enabled = false;

Optionally you can define the OnPause and OnContinue members:

protected override void OnPause() {

protected override void OnContinue() {

4. The timer's Elapsed Event handler.

timer.Elapsed += new ElapsedEventHandler( this.ServiceTimer_Tick );

This line instructs the Framework to call the "ServiceTimer_Tick" method within our current class when the timer elapses -- that is, when its interval runs its course. So we must implement this method in our class as such:

private void ServiceTimer_Tick(object sender, System.Timers.ElapsedEventArgs e) {

This is a bare bones version of our timer's elapsed event. Notice that we first "Stop()" the timer, execute the task, and then "Start()" it again. This prevents running into any problems if the code takes longer than the interval. This is optional, of course.

This is all we need for now in our Windows Service. The next step is to finish creating an installer class so we can install the Service into our system.

Step Two: Creating the Project Installer

The Project Installer is responsible for taking our Windows Service class and installing it into our system. We first need to create a class in our current project. Please name it "ProjectInstaller.cs".

Now I want to review each relevant line marked "//**'X'**" in the entire Project Installer code.

public class ProjectInstaller {

[RunInstaller(true)]  //**1**
	public class ProjectInstaller : System.Configuration.Install.Installer {  //**2**
	private System.ComponentModel.Container components;
	private System.ServiceProcess.ServiceInstaller serviceInstaller1; //**3**
	private System.ServiceProcess.ServiceProcessInstaller serviceProcessInstaller1; //**4**

		public ProjectInstaller() {

	private void InitializeComponent() {
		this.serviceInstaller1 = new System.ServiceProcess.ServiceInstaller();
		this.serviceProcessInstaller1 = new System.ServiceProcess.ServiceProcessInstaller();

		this.serviceInstaller1.DisplayName = "Scheduler_Net";  //**5**
		this.serviceInstaller1.ServiceName = "Scheduler_Net";  //**6**

		this.serviceInstaller1.StartType = System.ServiceProcess.ServiceStartMode.Automatic;  //**7**

		this.serviceProcessInstaller1.Account = System.ServiceProcess.ServiceAccount.LocalSystem;  //**8**
		this.serviceProcessInstaller1.Password = null;  //**9**
		this.serviceProcessInstaller1.Username = null; 

		this.Installers.AddRange(new System.Configuration.Install.Installer[] {



#1. Taken right out of the VS .NET documentation:

"Specifies whether an installer should be invoked during installation of an assembly." (ms-help://MS.VSCC/MS.MSDNVS/cpref/html/frlrfSystemComponentModelRunInstallerAttributeClassTopic.htm)

#2. Notice that our ProjectInstaller class must be derived from the Framework-supplied "System.Configuration.Install.Installer"

#3. The Install Utility needs a ServiceInstaller when it installs the Service application. It contains properties for such things as the Service Display Name, the Service name, Start Type, etc.

#4. A ServiceProcessInstaller is the actual class that will install the ServiceInstaller and its executable into the system, typically through the use of a tool such as "InstallUtil.exe" (more on this later).

If you would like to read more on these, please refer to the documentation (ms-help://MS.VSCC/MS.MSDNVS/cpref/html/frlrfSystemServiceProcessServiceInstallerClassTopic.htm).

#5 and #6. Demonstrates how to use the ServiceInstaller to set the desired DisplayName and ServiceName of the Service that is going to be installed.

#7. Demonstrates how to set the StartType of the Service. Your options include:

  1. Automatic
  2. Disabled
  3. Manual
#8. Demonstrates how to use the ServiceProcessInstaller to specify the desired default user account this Service will use once installed.

#9. Demonstrates how we could set the username and password if we were to choose the option, "System.ServiceProcess.ServiceAccount.User", for the desired user account.

#10. This binds the ServiceProcessInstaller, along with our ServiceInstaller, into our Installers. Installers are inherited from our derived class. Again, if you want more information on this, please consult the documentation (ms-help://MS.VSCC/MS.MSDNVS/cpref/html/frlrfSystemConfigurationInstallInstallerClassInstallersTopic.htm).

Step Three: Creating the Configuration File

The easiest way to configure the service is though the standard "APPNAME.EXE.config" (config) file, which the Framework automatically allows you to use through the "System.Configuration.ConfigurationSettings" class. With this class, we can actually create separate sections within the same configuration file, one for the service itself and others for any plug-ins we create. This simplifies administration to one XML file.

As mentioned in step one, #2, we are using the "System.Configuration.ConfigurationSettings" class to read the Timer interval into our class. It is using the standard "appSettings" section in the config file. See the XML snippet in Figure 1.2 below.

For our purposes we want to create and use different sections for our plug-ins. We first need to create a "configSections" node with a "sectionGroup" for our plug-ins. The easiest way to describe this is to look at a slimed down version of the config file.

<?xml version="1.0" encoding="utf-8" ?>
  <!-- application specific settings -->
    <sectionGroup name="PlugInSettings">
      <!--notice we have an entry for each plugin's settings node below-->

        <section name="TemplatePluginSettings" type="System.Configuration.NameValueSectionHandler" />
    <add key="servicepollinterval" value="10000" />       

      <add key="whatever" value="whatever-value" />

Figure 1.2 A snippet of the XML Configuration File

To use the different sections for each item under the PlugInSettings node, you will need to create a special collection for that section. In part 2, we will develop custom plug-ins to interface with the Windows Service.

About the Author

Robert Chartier has developed IT solutions for more than nine years with a diverse background in both software and hardware development. He is internationally recognized as an innovative thinker and leading IT architect with frequent speaking engagements showcasing his expertise. He's been an integral part of many open forums on cutting-edge technology, including the .NET Framework and Web Services. His current position as vice president of technology for Santra Technology has allowed him to focus on innovation within the Web Services market space.

He uses expertise with many Microsoft technologies, including .NET, and a strong background in Oracle, BEA Systems, Inc.'s BEA WebLogic, IBM, Java 2 Platform Enterprise Edition (J2EE), and similar technologies to support his award-winning writing. He frequently publishes to many of the leading developer and industry support Web sites and publications. He has a bachelor's degree in Computer Information Systems.

Robert Chartier can be reached at



  • hackett london

    Posted by gogoycj on 05/14/2013 07:16pm

    I just could not go away your site before suggesting that i actually loved the standard info an individual provide on your visitors? Is going to be back often in order to check out cross-check new posts hackett london Toms Dedicates To Offer Innovative And Comfortable Shoes ray ban

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Anthony Christie, the Chief Marketing Officer for Level Communications, is responsible for customer experience, worldwide marketing and product management. In this informative asset, he shares his insights into why a private network connection to cloud-bases applications is the right decision for your enterprise. Download now to find out more.

  • Enterprises are increasingly looking to platform as a service (PaaS) to lower their costs and speed their time to market for new applications. Developing, deploying, and managing applications in the cloud eliminates the time and expense of managing a physical infrastructure to support them. PaaS offerings must deliver additional long-term benefits, such as a lower total cost of ownership (TCO), rapid scalability, and ease of integration, all while providing robust security and availability. This report …

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date