I'd like to share my experience about a valuable OSS project I liked very much & used recently.
The latest project I designed & implemented was an integration subsystem that acts as a bridge between two systems, our B2C Portal & e-Government Message-based Services.
The solution architecture is based on building multiple multi-threaded windows services that receive, parse, initiate and send different types of requests & transactions between both systems bidirectional.
Building this number of windows services required building a good common infrastructure for all services to make them consistent enough, well refactored, and easy to debug.
And, Here came the decision to use Topshelf as an infrastructure for my services. Topshelf describes itself as "An easy service hosting framework for building Windows services using .NET"
What I liked about Topshelf, as a first reason to search about it & use it, that It enables you to build Windows service as a console application and run & debug it as a console application but you can deploy it as a Windows service. This idea sounds very good for me. So my services shouldn’t inherit from a specific class and shouldn't install them during development time before each debug session & uninstall them again.
Edit: Installing Topshelf became quite easy because of NuGet integration with Visual Studio 2010.
Other wise, you can simply download binaries & add references to you project.
So, let's see how it's easy to use Topshelf! All what I need is an empty console application and in the main method let's write the following.
1: const string SERVICE_NAME = "Do Something Service";
2:
3: // configure log4net
4: XmlConfigurator.Configure(PathHelper.GetFileInfo("do_something_service.log4net"));
5:
6: // configure service runner or host
7: HostFactory.Run(cfg => {
8: cfg.Service<IDoSomethingService>(svc => {
9: svc.SetServiceName(SERVICE_NAME);
10: svc.ConstructUsing(name => new DoSomethingService());
11: svc.WhenStarted(service => service.Start());
12: svc.WhenStopped(service => service.Stop());
13: }); cfg.RunAsLocalSystem();
14: cfg.SetDescription(SERVICE_NAME);
15: cfg.SetDisplayName(SERVICE_NAME);
16: cfg.SetServiceName(SERVICE_NAME);
17: });
Those few lines will make the console application work both as console application, as expected, and also as a Windows service that can be installed & controlled from Services Manager.
The code shown above is very generic so it doesn’t require implementing specific interfaces or to inherit from specific base classes. You can see method signatures below to make sure it’s all generic.
1: void ConstructUsing(Topshelf.Model.DescriptionServiceFactory<TService> serviceFactory);
2: void WhenStarted(System.Action<TService> startAction);
3: void WhenStopped(System.Action<TService> stopAction);
To implement my services, first, I created custom interfaces. First interface called IGenericService that will be a base for all service classes. Then, I create a custom interface for each service. For instance, I create DoSomethingService, I use an interface IDoSomethingService that inherits from IGenericService.
1: public interface IGenericService {
2: void Start();
3: void Stop();
4: }
5:
6: public interface IDoSomethingService : IGenericService {
7: }
8:
9: public class DoSomethingService : IDoSomethingService {
10: void Start() { return; }
11: void Stop(){ return; }
12: }
Now, you can easily install your console application executable as a Windows service through the following command line: {console_exe} install Or {console_exe} uninstall to uninstall it.
Then, using Services Manager you can control the service as needed.
There’s another way to host services built by Topshelf called shelving but I was interested in stand-alone Windows services that I can control through Services Manager.
That was a quick dumb of steps I went through during building my services. I hope it was useful.
Questions are welcome :)