I've been using TopShelf in production settings for a few years now and have been more than pleased. We have yet to discover any issues related to using the library. And new developers find it extremely easy to pick up.
I've just rolled out a service using TopShelf having not used it previously. It really does simplify things. The best bit for me is being able to just hit F5 and having the thing run as a console application. No need to manually attach to processes for debugging.
This technique lets you debug your service as if it were a console app - just pass in -a on the command line.
In your Main method:
if (args.Length > 0 && args[0] == "-a")
{
// Running as an application
MyService ms = new MyService();
ms.DoStart();
Console.WriteLine("Press Enter to Stop");
Console.ReadLine();
ms.DoStop();
} else {
// Running as a service
ServiceBase[] servicesToRun = { new MyService() };
ServiceBase.Run(servicesToRun);
}
And in the MyService class that derives from ServiceBase:
protected override void OnStart(string[] args)
{
DoStart();
}
protected override void OnStop()
{
DoStop();
}
internal void DoStart()
{
// Start your service thread here
}
internal void DoStop()
{
// Tell your service thread to stop here
}
It's definitely superior to hand rolling Windows services. We have something like 6 or 7 TopShelf-based services, a couple of which are self-hosted WebAPI endpoints. No problems or gotchas that I can remember, aside from slightly marginal documentation last time I looked.
I think my problem was using the Custom Service style, rather than inheriting from ServiceControl. There are a number of ways to interact with the HostConfiguration.Service<T>() method and its overloads, but there's only one tiny section in the documentation.
TBH, I think you might want to deprecate that whole way of using TopShelf. Using ServiceControl is much much easier and better documented. I think if one wants to keep TopShelf out of their core code, it's easier to create a separate "ServiceWrapper" project that has a ServiceControl subclass and calls into your other code, rather than using the HostControl.Service() style.