Controlling Windows Services

Creating a Windows Service using the .NET Framework is pretty easy. Here’s a quick primer, in case you don’t know what that is about:

The base class System.ServiceProcess.ServiceBase will give you what you need to create a Windows Service. It exposes several “events” in the lifecycle of a service (Start, Stop, Pause, Continue, Power- and Shutdown) as overridable On… methods (such as OnPause). The static entrypoint of the service executable needs to register the service main functions (as there can be more than a single service inside an .exe) and you’re done.

public class FileProcessorService: ServiceBase
  public static void Main()
    ServiceBase[] servicesToRun;
    servicesToRun = new ServiceBase[] { new FileProcessorService() };
  protected override void OnStart(string[] args) { … }
  protected override void OnStop() { … }

The Visual Studio .NET template for a Windows Service project will give you all this. Now you only need to register the service in the OS by running installutil.exe on the service assembly.

You should have a running Windows Service after it starts successfully. But wait… We need some more. How about a nice program that allows control over the service? Great, make it like the SQL Server Service Manager. Easy enough I say. Simply create a Forms application and drop a NotifyIcon control on it, plus drag the service from VS.NET Server Explorer onto the form. The ServiceController object can start, stop, pause and continue the service is has configured in the ServiceName property. It can even do so on remote machines if the MachineName property is set (security restrictions may apply).

You say you want even more? Be able to send requests to the service? This is where the options starts to get thin. There is a way to send simple commands TO the service (see below). Out of the box (.NET) services offer no way to communicate FROM the service to you. In more involved cases you will need to roll your own mechanism to communicate, like Web Services, .NET Remoting (nice article here), or intermediate storage (in files, databases or logs).

The way to send commands uses a Service Control Handler function beneath the covers. It allows you to send simple integer based commands to the service. The command IDs need to be between 128 and 256. Below 128 the IDs are system-reserved. Here’s what to do to implement it:

  • In service class override OnCustomCommand method
  • Add logic to run command based on integer command ID
    • switch case to invoke multiple commands
    • integer can be argument of single ‘function’
  • Make the ServiceController object call
    ExecuteCommand(int command) method, passing in the desired command ID.
  • Service Control Manager (SCM or ‘skum’) takes care of the rest

E.g. let’s say you have a Windows Service that does a period thingie, like synchronizing heterogeneous databases (right, Remco?). It might be enough to kick the service into doing it instantly (say from a tray icon context menu) by sending a command. On the other hand, when you want status progress of the synchronization (involving information from the service to you) you may have to resort to using the aforementioned communication techniques such as .NET Remoting.

You be the judge on whether this simple OnCustomCommand mechanism is enough for your situtation.

This entry was posted in Uncategorized. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s