Click here to Skip to main content
Click here to Skip to main content

Creating a Basic Windows Service in C#

, 5 Jun 2006
Rate this:
Please Sign up or sign in to vote.
A basic, easy-to-use template for a Windows Service in C# 2.0.

Introduction

Do a search some time on Google for Services and C#, and you'll come across a lot of ASP.NET references for web services. Not very useful for a beginner looking for info on Windows Services! I've had this very problem, so I decided to do it myself, the old-fashioned way. This article in not intended to contend with anyone else's article. It is simply a basic skeleton of a Windows Service, nothing more.

I know that in Visual Studio 2003, there was a template for a Windows Service, but I also remember it was rather obfuscated by Microsoft as far as templates go. Now that I use Visual C# 2005 Express Edition, there is no template for Windows Services. So, starting from there, I created one that works in .NET 2.0.

The Process

Here's a small example on how to build a Windows Service in C#.

First, load up your IDE of choice (mine is the free Visual C# 2005 Express Edition) and create an empty project. You can do this in VC# 2005 EE by clicking the menus: [File]->[New Project], Select "Empty Project", and name it what you will (mine is called WindowsService, original!). Click OK to create the project. Your project is created, and initially, it's not saved anywhere but a temporary location, so go ahead and go to [File]->[Save All], and okay through the dialog. This will officially save your project.

Next, add the System.ServiceProcess and System.Configuration.Install references to your project. In the Solution Explorer, right-click "References", and select "Add Reference...". In the dialog box that pops up, make sure the ".NET" tab is selected, and then scroll down in the list to "System.ServiceProcess", select it, and click OK. You'll see a new entry under References. This will allow you to write code that references the System.ServiceProcess classes. Repeat the process to add the System.Configuration.Install reference.

Now, add two new class files to the project, one labeled: "WindowsService.cs" and the other: "WindowsServiceInstaller.cs". In the Solution Explorer, right-click the project name and go to: [Add]->[Class]. Name the class "WindowsService.cs" and then hit OK. Repeat the process for "WindowsServiceInstaller.cs". Now you have two brand-new files with the basics.

In the "WindowsService.cs" class, copy the following:

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

namespace WindowsService
{
    class WindowsService : ServiceBase
    {
        /// <summary>
        /// Public Constructor for WindowsService.
        /// - Put all of your Initialization code here.
        /// </summary>
        public WindowsService()
        {
            this.ServiceName = "My Windows Service";
            this.EventLog.Log = "Application";
            
            // These Flags set whether or not to handle that specific
            //  type of event. Set to true if you need it, false otherwise.
            this.CanHandlePowerEvent = true;
            this.CanHandleSessionChangeEvent = true;
            this.CanPauseAndContinue = true;
            this.CanShutdown = true;
            this.CanStop = true;
        }

        /// <summary>
        /// The Main Thread: This is where your Service is Run.
        /// </summary>
        static void Main()
        {
            ServiceBase.Run(new WindowsService());
        }

        /// <summary>
        /// Dispose of objects that need it here.
        /// </summary>
        /// <param name="disposing">Whether
        ///    or not disposing is going on.</param>
        protected override void Dispose(bool disposing)
        {
            base.Dispose(disposing);
        }

        /// <summary>
        /// OnStart(): Put startup code here
        ///  - Start threads, get inital data, etc.
        /// </summary>
        /// <param name="args"></param>
        protected override void OnStart(string[] args)
        {
            base.OnStart(args);
        }

        /// <summary>
        /// OnStop(): Put your stop code here
        /// - Stop threads, set final data, etc.
        /// </summary>
        protected override void OnStop()
        {
            base.OnStop();
        }

        /// <summary>
        /// OnPause: Put your pause code here
        /// - Pause working threads, etc.
        /// </summary>
        protected override void OnPause()
        {
            base.OnPause();
        }

        /// <summary>
        /// OnContinue(): Put your continue code here
        /// - Un-pause working threads, etc.
        /// </summary>
        protected override void OnContinue()
        {
            base.OnContinue();
        }

        /// <summary>
        /// OnShutdown(): Called when the System is shutting down
        /// - Put code here when you need special handling
        ///   of code that deals with a system shutdown, such
        ///   as saving special data before shutdown.
        /// </summary>
        protected override void OnShutdown()
        {
            base.OnShutdown();
        }

        /// <summary>
        /// OnCustomCommand(): If you need to send a command to your
        ///   service without the need for Remoting or Sockets, use
        ///   this method to do custom methods.
        /// </summary>
        /// <param name="command">Arbitrary Integer between 128 & 256</param>
        protected override void OnCustomCommand(int command)
        {
            //  A custom command can be sent to a service by using this method:
            //#  int command = 128; //Some Arbitrary number between 128 & 256
            //#  ServiceController sc = new ServiceController("NameOfService");
            //#  sc.ExecuteCommand(command);

            base.OnCustomCommand(command);
        }

        /// <summary>
        /// OnPowerEvent(): Useful for detecting power status changes,
        ///   such as going into Suspend mode or Low Battery for laptops.
        /// </summary>
        /// <param name="powerStatus">The Power Broadcast Status
        /// (BatteryLow, Suspend, etc.)</param>
        protected override bool OnPowerEvent(PowerBroadcastStatus powerStatus)
        {
            return base.OnPowerEvent(powerStatus);
        }

        /// <summary>
        /// OnSessionChange(): To handle a change event
        ///   from a Terminal Server session.
        ///   Useful if you need to determine
        ///   when a user logs in remotely or logs off,
        ///   or when someone logs into the console.
        /// </summary>
        /// <param name="changeDescription">The Session Change
        /// Event that occured.</param>
        protected override void OnSessionChange(
                  SessionChangeDescription changeDescription)
        {
            base.OnSessionChange(changeDescription);
        }
    }
}

In the "WindowsServiceInstaller.cs" class, copy the following:

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

namespace WindowsService
{
    [RunInstaller(true)]
    public class WindowsServiceInstaller : Installer
    {
        /// <summary>
        /// Public Constructor for WindowsServiceInstaller.
        /// - Put all of your Initialization code here.
        /// </summary>
        public WindowsServiceInstaller()
        {
            ServiceProcessInstaller serviceProcessInstaller = 
                               new ServiceProcessInstaller();
            ServiceInstaller serviceInstaller = new ServiceInstaller();

            //# Service Account Information
            serviceProcessInstaller.Account = ServiceAccount.LocalSystem;
            serviceProcessInstaller.Username = null;
            serviceProcessInstaller.Password = null;

            //# Service Information
            serviceInstaller.DisplayName = "My New C# Windows Service";
            serviceInstaller.StartType = ServiceStartMode.Automatic;

            //# This must be identical to the WindowsService.ServiceBase name
            //# set in the constructor of WindowsService.cs
            serviceInstaller.ServiceName = "My Windows Service";

            this.Installers.Add(serviceProcessInstaller);
            this.Installers.Add(serviceInstaller);
        }
    }
}

The ServiceAccount section of the code is important for the security context under which your code will run. For every enumeration except User, set the Username and Password properties to null.

You can set the Account property to the following (this is mostly from Microsoft's help file):

  • The LocalSystem enumeration defines a highly privileged account, but most services do not require such an elevated privilege level.
  • The LocalService enumeration provides a lower privilege level for the security context.
  • The NetworkService enumeration provides extensive local privileges, and provides the computer's credentials to remote servers.
  • The User enumeration allows the use of a username and password combination to set the privilege level for the security context to that of a specified user.

There. That wasn't so tough! Now, in the WindowsService class, depending on what you're creating this service for, you'll probably want to include a background working thread to handle, well, the work. I've used this code simply by leaving everything as-is with just the OnCustomCommand method modified, and it works OK. If you wish to handle constant or timed processing, best add at least one working thread.

That's as far as I'll go in this article on setting up a Windows Service: everything else is pretty much up to the programmer. Now, the easy/hard part: Installation.

Installation

To install a service, you could create an installation program that encapsulates the executable for deployment, which I find time consuming and inefficient when testing an application. Or, you could install the service though the InstallUtil.exe process that comes with the .NET Framework.

I created a simple batch file, install.bat, to simplify installation (and therefore testing) of the service. The batch script is shown below; uninstallation is as simple as creating another batch file, uninstall.bat, with exactly the same script, only substituting the /i (for install) with /u (for uninstall).

@ECHO OFF

REM The following directory is for .NET 2.0
set DOTNETFX2=%SystemRoot%\Microsoft.NET\Framework\v2.0.50727
set PATH=%PATH%;%DOTNETFX2%

echo Installing WindowsService...
echo ---------------------------------------------------
InstallUtil /i WindowsService.exe
echo ---------------------------------------------------
echo Done.

Points of Interest

I have noticed that other examples on creating services (when I can find them) are more focused on everything *but* the actual creation and structure of a Windows service. Since I did this mainly for a work project, I had to learn this all on my own, which in itself is rewarding, but I can imagine how other people feel when they need this kind of code as soon as possible and don't have the time to research it. Hopefully, this will help others who need just the basics and can go from there.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

John Storer II
Software Developer Employer's Security
United States United States
I'm a Computer Support Technician for a Indiana School System. Really, I'm a C#/ASP.NET Developer in a Software Support coat. Jack-of-all-trades, I do Hardware Support, Software Support, Programming in C#.NET, ASP.NET / Javascript, Web Design, Graphic Arts and lots of other stuff.
 
I've been programming almost 21 years now, and have used more than 10 different languages in the past.

Comments and Discussions

 
QuestionThanks Pinmemberkarthik cad/cam13-Aug-14 1:09 
QuestionVery Good PinmemberCesar A. Grachik15-Jul-14 11:48 
QuestionOutput Type - VS 2008 PinmemberBigFish200025-Mar-14 17:41 
GeneralPerfect introductory article. PinmemberDaveDbViewSharp24-Feb-14 9:42 
QuestionHow to create a simple Windows Service in C# and Install it using Installutil Pinmemberberkut20066-Nov-13 14:44 
GeneralMy vote of 5 Pinmemberrmkamal2-Oct-13 1:34 
GeneralMy vote of 5 Pinmemberngjafo19-Sep-13 3:37 
GeneralMy vote of 4 Pinmembersheik sadath8-Sep-13 20:28 
QuestionAcknowledgment PinmemberCungaLunga2-Sep-13 20:18 
QuestionGeneral feedback PinmemberMember 836242719-Jul-13 4:30 
GeneralMy vote of 5 Pinmembermichael7824418-Jul-13 3:21 
GeneralMy vote of 5 PinprofessionalEdo Tzumer30-Jun-13 5:02 
GeneralMy vote of 3 PinmemberInba karthik7-May-13 1:19 
GeneralMy vote of 4 PinmemberSymbios30-Apr-13 12:19 
GeneralMy vote of 3 PinmemberAvdhesh kumar4-Mar-13 22:06 
GeneralMy vote of 5 PinmemberModel1230-Jan-13 9:41 
SuggestionFind a new job PinmemberKenneth Bullock29-Dec-12 21:47 
GeneralRe: Find a new job Pinmembersupernorb15-Jun-13 8:10 
GeneralMy vote of 5 PinmemberMember 892757828-Sep-12 6:09 
AnswerMy vote is 5+ Pinmemberjmptrader25-Jul-12 19:08 
GeneralMy vote of 5 Pinmembermanoj kumar choubey23-Jul-12 0:23 
SuggestionFailed to install the service PinmemberMember 471378517-Jul-12 20:55 
GeneralRe: Failed to install the service PinmemberJohn Storer II18-Jul-12 1:13 
GeneralRe: Failed to install the service [modified] PinmemberSpiff Dog18-Oct-13 16:28 
GeneralRe: Failed to install the service Pinmemberx0lubi2-Apr-14 12:53 
GeneralMy vote of 5 PinmemberMember 91875854-Jul-12 0:46 
GeneralCompliment PinmemberMember 91875854-Jul-12 0:43 
QuestionCompliments PinmemberApurva Kunkulol14-May-12 0:22 
GeneralMy vote of 5 PinmemberFerBri10-May-12 5:14 
QuestionGreat Service Example PinmemberFireBall17257-May-12 3:15 
GeneralMy vote of 5 PinmemberAlbert van Peppen16-Apr-12 0:16 
GeneralMy vote of 4 Pinmembermbsmbs11-Apr-12 3:23 
GeneralMy vote of 4 Pinmembertcables13-Mar-12 6:30 
QuestionThx! PinmemberDavid Catriel9-Jan-12 3:59 
GeneralThanks Pinmemberrizwan008-Dec-11 20:13 
QuestionDistribution PinmemberWjousts9-Aug-11 3:29 
AnswerRe: Distribution PinmemberWjousts9-Aug-11 5:01 
GeneralMy vote of 5 Pinmemberhimz_him7-Jun-11 22:32 
GeneralMy vote of 3 PinmemberMember 794484523-May-11 1:15 
Generalwindows service [modified] PinmemberJuan Carlos Gonzalez11-May-11 13:07 
GeneralRe: windows service Pinmemberluisperezphd19-May-11 6:34 
GeneralCan the C# windows service access a serial port? Pinmemberhbe0223-Apr-11 12:19 
GeneralRe: Can the C# windows service access a serial port? PinmemberJohn Storer II23-Apr-11 16:31 
GeneralRe: Can the C# windows service access a serial port? PinmemberWjousts9-Aug-11 5:02 
GeneralMy vote of 5 PinmemberJames Schuldiner27-Mar-11 11:59 
GeneralCreating simple windows service PinmemberRanjano20-Feb-11 9:31 
GeneralRe: Creating simple windows service PinmemberJohn Storer II20-Feb-11 9:39 
GeneralMy vote of 4 Pinmemberfrancesco.alesiani17-Feb-11 4:28 
Generalconfig file is not available under installation folder PinmemberJoe Babu12-Jan-11 20:58 
Generalwindow service in c# Pinmemberamitrajahuja2-Dec-10 22:40 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web03 | 2.8.140902.1 | Last Updated 5 Jun 2006
Article Copyright 2006 by John Storer II
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid