Windows Services in C#: Getting Started (part 2)

Yesterday we covered the basics you need to understand in order to write Windows Services. With that out of the way, it’s time to roll up our sleeves and write some code.

To get started, open Visual Studio and select new project. Windows Service won’t appear in the top level list of Visual C# items, instead you’ll need to drill down and in the tree under Visual C# select Windows. Now you should see “Windows Service” appear in the list of templates. Pick it, then go down and key in a name. For this demo I’m going to do something very simple, so let’s call it “TimeLogger” and press OK.

[New Project Dialog]

Now let’s take a moment to see what has been created for us. Over the in the solution explorer, beside the properties and references you’ll see two files, program.cs and service1.cs. Let’s look inside Program.cs, shall we?

    static void Main()

    {

      ServiceBase[] ServicesToRun;

 

      // 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 ServiceBase[] {new Service1(), new MySecondUserService()};

      //

      ServicesToRun = new ServiceBase[] { new Service1() };

 

      ServiceBase.Run(ServicesToRun);

    }

 

This simple code does an incredible amount. First, it creates an array of ServiceBase objects named ServicesToRun. This will hold the list of all the services this project will hold. Next it adds the single service that was automatically generated for you, Service1, to the array, and finally it calls the Run method to launch all of the services.
 
The first thing we’ll want to do is change the name of Service1 to something more meaningful. Click on the file name in Solution Explorer, and change it’s name from Service1 to TimeLoggerService. You’ll then be asked if you want to change all references, say Yes to let VS take care of all the work for you. You should now see that Program.cs has been updated:
 

      ServicesToRun = new ServiceBase[] { new TimeLoggerService() };

If you had other services to run, you’d add them to the array prior to the ServiceBase.Run command. What’s important to note though is the Run command launches the service file in it’s own thread, then keeps on trucking returning control back to windows.

Specifically, it’s the Service Control Manager (SCM) which is launching your app via the Main method in program.cs, then expecting control back. If you didn’t use Run, but instead tried to process a bunch of time consuming commands, the SCM would eventually time out and report your service failed to start. For that reason it’s important to put no extra code in the Main method other than what’s needed to get to the ServiceBase.Run command.

Now let’s take a look at the TimeLoggerService class. Double click on it in the Solution Explorer, and you will see a new editor tab appear with “TimeLoggerService.cs [Design]” in the title. The big gray area doesn’t show you much, so let’s ignore it for right now and look at the Properties window.

The most important property is ServiceName. This is the one you really want to change, as it’s the one that shows up throughout the Windows infrastructure. Windows can only have one version of a service going, so if you don’t change it the next project you start will also have the default name “Service1” and the two will collide like an iceberg with the Titanic. I’m changing the name to ArcaneTimeLogger.

AutoLog is another property to note, when true (the default) messages for the starting, stopping, etc. of your service will be taken care of for you. Since you can never have too much info, I would leave this set to true.

Next are a series of “Can” properties: CanHandlePowerEvent, CanHandleSessionChange, CanPauseandContinue, CanShutdown, and CanStop. If any of these are set to true, you will have to then insert a method to handle the event (or events in the case of Pause and Continue).

OK, that handles all of the important properties we need to examine. Let’s look at some code. Open the TimeLoggerService.cs so you can see the code.

  public partial class TimeLoggerService : ServiceBase

  {

    public TimeLoggerService()

    {

      InitializeComponent();

    }

 

    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.

    }

  }

The first thing you should notice is our class inherits from ServiceBase. The ServiceBase has two methods you must implement, OnStart and OnStop, and you’ll notice Visual Studio has helpfully created them for you. If you want to start your own service class from scratch, be sure to inherit from ServiceBase and implement these two methods.

Now let’s add a little code. We’ll add a timer and log the time every minute. Here’s the complete class:

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Diagnostics;

using System.ServiceProcess;

using System.Text;

using System.Timers;

 

namespace TimeLogger

{

  public partial class TimeLoggerService : ServiceBase

  {

    // Note we had to add System.Timers to the using area

    private Timer _timer = null;

 

    public TimeLoggerService()

    {

      InitializeComponent();

      // Set the timer to fire every sixty seconds

      // (remember the timer is in millisecond resolution,

      //  so 1000 = 1 second. )

      _timer = new Timer(60000);

 

      // Now tell the timer when the timer fires

      // (the Elapsed event) call the _timer_Elapsed

      // method in our code

      _timer.Elapsed += new

        System.Timers.ElapsedEventHandler(_timer_Elapsed);

    }

 

    protected override void OnStart(string[] args)

    {

      _timer.Start();

    }

 

    protected override void OnStop()

    {

      _timer.Stop();

    }

 

    protected override void OnContinue()

    {

      base.OnContinue();

      _timer.Start();

    }

 

    protected override void OnPause()

    {

      base.OnPause();

      _timer.Stop();

    }

 

    protected override void OnShutdown()

    {

      base.OnShutdown();

      _timer.Stop();

    }

 

    // This method is called when the timer fires

    // it’s elapsed event. It will write the time

    // to the event log.

    protected void _timer_Elapsed(object sender, ElapsedEventArgs e)

    {

      EventLog evt = new EventLog(“ArcaneTimeLogger”);

      string message = “Arcane Time:”

        + DateTime.Now.ToShortDateString() + ” “

        + DateTime.Now.ToShortTimeString();

      evt.Source = “ArcaneTimeLoggerService”;

      evt.WriteEntry(message, EventLogEntryType.Information);

    }

  }

}

The code is pretty self explanatory; I added OnContinue, OnPause (which are the implementations of CanPauseAndContinue), and OnShutdown (for CanShutdown) methods and set those properties to true. I then added a method, _timer_Elapsed, that will do all the work when the timer fires. Also note I had to add a reference to System.Timers to be able to use them.

OK, we now have a spiffy new service just eager and ready to be run. Well, if you recall from part 1 you simply can’t run a windows service, you have to install it. And that’s a big subject we’ll cover tomorrow in part 3!

17 thoughts on “Windows Services in C#: Getting Started (part 2)

  1. Thanks. It took me a while to find an article that is up with the current ver of VS and dotnet. Helped me greatly.

  2. I’m using VS 2008 and couldn’t get the timer event to log anything. After a little Googling and trying a few things, I got the following to work:

    protected void _timer_Elapsed(object sender, ElapsedEventArgs e)
    {
    string sSource = “ArcaneTimeLogger”;
    string sLog = “Application”;

    if (!EventLog.SourceExists(sSource))
    EventLog.CreateEventSource(sSource, sLog);

    EventLog evt = new EventLog();
    string message = “Arcane Time:”
    + DateTime.Now.ToShortDateString() + ” ”
    + DateTime.Now.ToShortTimeString();
    evt.Source = “ArcaneTimeLogger”;
    evt.WriteEntry(message, EventLogEntryType.Information);
    }

  3. Hi friend i want to show windows form on the timer elapsed event in winservice program. Please reply me if this possible.
    thanks

  4. Deepak – Can’t be done. Windows Services are not allowed to display any kind of user interface, as they are designed to be run “unattended”.

    Imagine a server with no one logged in, and one of it’s windows services started displaying messages for no one to see? Lots of problems.

    What you could do is have the service write it’s messages to the event log. Then write a separate program, maybe it could be an app that runs in the system tray. It’s job would be to monitor the event log and look for messages your service writes. When it sees a new one it could then pop up the window you are wanting to display.

  5. In case anyone has this too.

    When you cut and paste the _timer_Elapsed code, make sure that the double quotes are not Microsoft Word annoying ‘special’ slanted quotes.
    Just type them in manually in your code window to be sure.

  6. Can you please tell me can we stop the timer on ealsped event to make the transactions to be ended successfully and then start the timer after getting the successful response is it possible to do so plz reply

  7. Sahar, I would say certainly.

    protected void _timer_Elapsed(object sender, ElapsedEventArgs e)
    {

    _timer.Enabled = false;
    // do your stuff
    _timer.Enabled = true;
    }

    You would of course need to check that your code worked as otherwise the timer may neer get restarted.

  8. Hi all!

    I want to generate a window service using c# for a window application for startup and stop, so that every time the user turn on the computer the application (attendance system) pop-up appear and during turning outthe computer the pop-up again appear on the desktop automatically, so that the user remember to logout for the day.

    1. Sorry but you can’t. Windows services don’t allow “pop ups” or any other type of user dialog to appear. That’s because Windows services can be running when no one is logged into the computer.

      I would instead suggest you write it as a System Tray type application. To be honest though it sounds like your application will wind up annoying the vast majority of your users, who will likely remember to login/off each day. I’m guessing the app will only be helpful for a small number, and I’m betting a lot of those who don’t log off don’t do so on purpose and a dialog is not going to change their behavior. I would look at some other method to try and alter the users behavior.

      1. You could use a group policy to run specific app at logon and apply the policy to only those individuals that needed to use the attendance system.

  9. Generally, when you start a service you expect it to start work immediately. As it stands your service waits for a minute before doing anything. You either need to call the _timer_Elapsed method manually or use System.Threading.Timer which allows you to specify an initial trigger delay and a repeat interval.

  10. Dear

    I have a create Windows Service and i want to start hello.exe from windows service.

    I have start hello.exe but its show as backupgroup[ show under System user] i want to start hello.exe on my current user.

    Thanks in advance

    Bhim Prakash Singh
    +91 9759020580

  11. Dear

    i have create a windows service. its run find. i need to show notifyicon from windows service. i using C# for this code.

    Thank in advance.

    Bhim Prakash Singh
    +91 9759020580

Leave a comment