Services

Running multiple windows services in a single process

Sometimes in a large business application, it’s convenient to have more than one windows service available to allow for certain pieces of the application to be managed separately.  This is possible to create in two ways.  The first is rather straight forward.  For every service to create, create a different windows service executable.

The second is still straight forward, but less common, and another useful tidbit I found while reading the MSDN documentation.  This is to make a single service executable which contains many services.  The advantage to this is that the application shares a same executable process.  This can reduce memory usage especially if the program does things such as cache data into memory.  Or, if certain services are dependent on others running, they can inspect whether the other is running using shared memory such as static variables.  I’m going to show you how to set this up.

When setting up the services, simply create a second service.  To wire it up, where your program runs, add both services to an array that gets passed to ServiceBase.Run().

ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[] 
{ 
    new MultiServiceI(), 
    new MultiServiceII()
};
ServiceBase.Run(ServicesToRun);

It’s as simple as that!  Create an extra service installer for your new service and you’ll be able to run them both.  When you start both the services, notice the PID in the task manager, you’ll notice it’s the same.

pid

To demonstrate that the services are actually sharing memory, in my “OnStart” method, I logged the service that is starting and the last service that started.  The strings have been change for the respective services.

Program.Log("Started MultiService I, Last Service Started = " + Program.LastService);
Program.LastService = "MultiService I";

The implementation of these two are quite simple in the Program class.

public static string LastService = "";
public static void Log(string logText)
{
    File.AppendAllLines("C:\\multiservice.log", new[] { logText });
}

So, after running the first service followed by the second service, I get this in my log file

Started MultiService I, Last Service Started = 
Started MultiService II, Last Service Started = MultiService I

As you can see, when I start the second service the name of the first service is output as the last service that was run.

I hope you find this useful.  You can find a full solution on my samples repository https://bitbucket.org/hondomon/samples/src/master/dotNET/WindowServices/MultiService

Advertisements