Windows Services in .NET (with Indy) #.NET #Delphi
As part of my team's project at work, we had to create a Windows service in .NET. Originally we built it in Delphi 8 for .NET, which worked fine as long as we could get the compiler to cooperate. But the D8 compiler is so buggy, especially when working with multi-assembly project groups, that we eventually wound up porting the service back to C#. Sigh.
Creating a Windows service in .NET is actually not too hard, though it isn't well documented. If you have Visual Studio, there's actually an option in File > New Project to create a Windows service. However, that doesn't do everything you need; specifically, it doesn't give you any way to install your service so that Windows will actually run it (or show it in the Services snap-in so you can start and stop it later). And if you have Delphi 8, you don't have a Windows service wizard. (There was one in D6, but apparently its .NET rewrite didn't make the D8 release schedule.)
This article on CodeProject was invaluable to us in getting things up and running. It shows how to build a .NET Windows service from the ground up; it doesn't assume that you have Visual Studio with its Windows service project wizard (which is handy if you're using Delphi 8, or if you only bought Visual C# instead of the full Studio, or if you're writing your code in SharpDevelop or Notepad). It also shows how to install (and uninstall) the service using installutil.
Once you've walked through the article, and have your service up and running, it's pretty slick. The service ends up as an EXE that's intended to run under Windows' service manager -- and the .NET service plumbing will automatically give the user a meaningful error message if they try to run the EXE manually (though there is about a 15-second pause first), which is good. And if your service is starting an HTTP server using the open-source Indy networking libraries (check them out if you're still using the wussy FTP and HTTP support in System.Net — Indy is better, and it supports just about every Internet protocol known to man, both client- and server-side, and it's free), then you don't even need to worry about the fact that there are something like three threads being created and juggled just to manage your service — it just works. Just set the server's Active property to true in your override of ServiceBase.OnStart, and set it back to false in your override of ServiceBase.OnStop. Indy will even wait for any pending HTTP requests to finish before it returns from the Active = false setter. Very cool.