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!

Windows Services in C#: Getting Started (Part 1)

On occasion you have need for an application that will run all of the time on a workstation or server, whether anyone is logged into that workstation, or perhaps running in the background. For those requirements you’ll want to create a Windows Service.

There are a few things you have to keep in mind when creating a Windows Service. The first, and most important is that there is no user interface. Because Windows Services run in the background, even when no user is logged in, most times (especially when running on a server) there is no one to display a user interface to. As such, things like MessageBoxes and Forms are not allowed. Instead, if you need to log messages and the like it’s recommend you use the Event Logger. (For more info see my series on event logging, it started on January 16 of this year and ran to the 19th, http://shrinkster.com/p6d).

The next thing you will want to decide is how you’d like your service to start. You have three choices; in Manual mode (which is the default) either a user or some program event must start the service. In Automatic mode, windows will automatically kick off the event for you, and start it running when Windows itself starts up. Finally, in Disabled mode, nobody can start it until the start up type is changed.

Now you need to think about security, what permissions will your service need? LocalService is the most secure, it gets sandboxed on a local station and any access to insecure tasks, such as writing to the hard disk, are restricted. This is a good choice when you want to create an app that monitors something on the box and logs it’s output to the event log, but needs little other in the way of resources.

For a server you might wish to bump up to NetworkService. This will allow communication with other PCs on the network, but still manages any potentially harmful access to the machine.

If you need unlimited privileges, you’ll need to set your security to LocalSystem. I encourage you to really think about this before you pick LocalSystem as your level, as you open yourself up to severe vulnerabilities if anyone were to hack your code. However I do recognize there are some cases where it’s the only way to make it work, or perhaps you are in a situation where it’s safe to do so (perhaps your machine is not on the internet).

The final, and default choice is User. With User, you pass in a user id and password, and your service has the same permissions as that user. The ideal situation would be to create a special user account just for this service, and set the permissions just high enough to get the job done, and no higher. Also you’ll likely want to setup an ID with a non-expiring password. If you omit a user id/password then the person who launches the service will be prompted for a valid user id/password at run time, probably not a desirable option.

You should also be aware that debugging a windows service is very different from your typical debugging, whether you are used to WinForms or ASP.Net coding. We’ll cover debugging in a post of its own later in this series.

Just as debugging is different, so is installation. Because of its nature a Windows service has to be installed, you can’t just copy it and run it. Fortunately Visual Studio makes it easy for you by generating a setup project you can use. Again, we’ll cover that later in the series.

OK, you now have all the background you need under your belt, tomorrow we’ll start generating some code!

Arcane Music to Program By

Most of us aren’t lucky enough to have a private office. Instead we are condemned to cubical life, often with noisy co-workers nearby. Coding, serious deep coding, requires intense concentration with a minimum of distraction. Thus a really good pair of headphones (preferably noise canceling) and some good tunes are a necessity of life.

When I’m really trying to get into the “zone” I find audio with words too distracting. Some jazz is nice, but often winds up being more relaxing than stimulating. For those times when I really need to get the code flowing I fire up something orchestral, like a movie soundtrack. Anything by John Williams or Danny Elfman is great. But for those times where I really need to crank out the code, I turn to my Midnight Syndicate collection.

I once heard Midnight Syndicate (http://www.midnightsyndicate.com) described as a group that writes “gothic horror soundtracks to movies that were never made”. Their music is an eerie, spooky, haunting, but most of all it really gets my creative juices flowing. It’s intense, without being too intense and burning you out.

I guess the description isn’t as accurate as it once was, since there are several films due for release in the near future they will be scoring, namely “The Rage” (http://www.theragefilm.com/) and “Sin-Jin Smyth” (http://www.sin-jinsmyth.com/).

A third film, “The Dead Matter” (http://www.thedeadmatter.com/) is being written and directed by Edward Douglas, half of the Midnight Syndicate. Gavin Goszka, the other half of Midnight Syndicate will serve as musical director and together they will create the soundtrack. If the title seems familiar, it’s actually going to be a remake of the 1996 version of “The Dead Matter” which Douglas directed, scored and produced.

I didn’t mean to turn this into a film and music review, I was just listening to my collection while sitting here on my back deck and working on this week’s posts, and decided to toss in a bonus post for the week.

If you are curious, head over to their website and click on “The Music” link over on the right. They list each album, and there’s a “listen to tracks’ link which takes you to their MySpace account where you can get a sampling from their albums. “Gates of Delirium” is probably my favorite, but “The 13th Hour” runs a close second.

Now, get back to work.

Standard disclaimer: I have no financial affiliation with Midnight Syndicate or Entity Productions, other than being a customer. I receive no consideration of any kind for this mention. I just think it’s some awesome music and wanted to share.

Arcane Fun Friday

Just thought I’d share a bit of fun today, I’ve found a cool website called InterfaceLIFT. (http://interfacelift.com/). It has wallpapers, icons, themes, etc to enhance your system. You can specify the size of wallpapers, and it includes sizes for the oddball laptop screens like mine, 1440×900. If you are looking for a way to spice up your install, or just get a few really nice looking wallpapers, this is a great resource, and even works with Vista!

Fixing Ubuntu 7.04 Fiesty Fawn Mouse under Virtual PC 2007

Update: October 18, 2007 – Ubuntu 7.10 was released today, and I’ve now posted step by step instructions for installing it. If you haven’t yet installed Ubuntu, you may prefer to start with the instructions on 7.10, found here: https://arcanecode.wordpress.com/2007/10/18/installing-ubuntu-710-under-virtual-pc-2007/


OK, one of my readers “John” (thanks John!) shared a link to an unsupported patch that fixed the Ubuntu 7.04’s mouse under Virtual PC. Let me give you the quick summary of what I did:

  1. Fired up a new VirtualPC with the Fiesty Fawn “Live CD” in the drive. Booted up in safe graphics mode.
  2. Once up, I activated the keyboard mouse using the fix I described in my post “Ubuntu 7.04 and Virtual PC 2007 – Mouse Issue Workaround (sort of)” at http://shrinkster.com/p2u.
  3. I then installed Ubuntu, it was pretty straightforward although a bit annoying using the numeric keypad as a mouse. One hint, sometimes it didn’t recognize my mouse click until I moved the mouse off a button then back on.
  4. After the install I rebooted, then in my new install repeated step 2 to activate the keyboard mouse in my new install. Setting this in the Live CD didn’t carry over to the new install.
  5. I then opened firefox and went to the link John provided, https://bugs.launchpad.net/ubuntu/+source/linux-source-2.6.20/+bug/87262/comments/13. Since that’s a lot of typing, I shrinksterized it to make it very easy to type, http://shrinkster.com/p2t.
  6. Joe Soroka has posted a script, I downloaded it using the “shell script” link at the very top of the message and saved it to my home folder.
  7. I opened my File Browser (use Left Alt+F1 select Places, Home Folder). I moved the mouse (again using the numeric keypad) and clicked once on the sh file I’d saved.
  8. Now in the browser, with the file highlighted, hit left alt+enter or select File, Properties on the File Browser menu.
  9. In the dialog that appears, move to the Permissions tab, and check on the box that says “Allow executing file as program”. Click the close button to close the dialog.
  10. Now double click the sh file or press enter. You should see a dialog appear that asks if you want to open in a text editor or run the script. Select the “run in terminal” option. (Update, added “in terminal” based on feedback.)
  11. While the script executes it will ask for your admin password, give it.
  12. At one point it will also stop to ask if you want to skip or configure grub manually, or let it do it for you. I pressed enter to let the script do it for me.
  13. That ended the app, when the terminal window closed I rebooted (still using the numeric keypad as my mouse).
  14. When Ubuntu came back up, it flashed a quick message from the grub asking which kernel I wanted to load, I just took the default.
  15. I logged in and what do you know, my mouse worked!

Just FYI, I’m running Virutal PC 2007 under Vista, using the standard desktop version of Ubuntu 7.04.

The real hero here is Joe Soroka for posting such a simple fix. I encourage you to give it a try. If you are concerned about messing up your Ubuntu install, simply copy the VHD/VPC files to a backup location before running the fix.

A big thanks to Joe Soroka, and to “John” for posting the link. Now I can actually start playing with Ubuntu 7.04.

BOHICA

I mentioned I was on a business trip, during our long road miles my co-worker and I listened to quite a few podcasts. One that was really interesting is the current episode of Security now, episode 91. (http://www.twit.tv/sn91).

In this episode Steve and Leo interview Marc Maiffret of eEye Digital Security (http://www.eeye.com/html/index.html) about the state of security both in the Enterprise and at home. In this episode Marc makes a starting yet fascinating assertion, namely that Microsoft Software is no longer the biggest vulnerability on the Windows platform. Instead, their research shows it’s other software that’s opening up vulnerabilities.

Part of the issue occurs because these vendors lack the concept of “Patch Tuesday” that MS has. Additionally, they tend to bundle their security fixes with other software updates. A user looks at a 47 meg update and goes “hmm, my app is running fine, don’t see a need to update” and misses all the security fixes.

Now, before some joker comes off with “run Linux it’s secure”, on a recent episode Steve talked about a Javascript exploit that can affect your router and effectively open it up. And yes, the exploit works on both Windows and Linux and it also runs under FireFox as well as IE. (Please note I’m not bashing Linux, I have it on a few of my boxes, I’m just realistic about its security abilities.)

The point I’m making here is to make sure to update ALL of your software. Like many I dutifully have my Microsoft updates run automatically each week, but have declined updates of other software thinking “nah, it’s working right now not gonna worry about it”. You can bet I won’t make that mistake again!

Arcane Recommendation: Coding Horror

I’m on the road again, so sporadic posts this week, but wanted to recommend something to you. I’m a big fan of Jeff Atwood’s Coding Horror site, http://www.codinghorror.com. Jeff has some really great insights into the coding process.

Recently Jeff was a guest on a great podcast, Dot Net Rocks. May I suggest it’d be well worth your time to listen to episode 232 (http://www.dotnetrocks.com/default.aspx?showNum=232)? Jeff has some great insights, and some great lines as well. I intend to expound on a few of these, so consider this a little “homework” for my upcoming post.