|Delphi Clinic||C++Builder Gate||Training & Consultancy||Delphi Notes Weblog||Dr.Bob's Webshop|
Performing a service
One evening early in february, we had a meeting to look at a new stuff and have discussions about various things. Every month we gather all consultants as far as that is possible to have such meetings. This time we discussed "a new toy to write great applications in C++". No. That's all I'm going to say at the moment. One of the things we tried is building an NT service...
Generating a service is easy enough. Just make a project that is a service application. Then add the controls you need to perform your services, configure the necessary properties to their correct and/or desired values and off we go. Err. Nope. We don't. The problem is how to start this application in what is generally known as the Service Control Manager. True enough, we generate an executable, and we even can run it, but what happens is that it just sits there for a couple of seconds and then exits. Consultation of the event log does not give us a good enough clue as what is happening here. Consultation of the online help that comes with C++ Builder also does not give a clue how to perform the necessary installation tasks to enable us to start the service.
Use the source, Luke!
Yep, the source can give you the force. Let's trace the chain of events here. From the included VCL header files one stood out as relatively interesting, namely <vcl/SvcMgr.hpp>. One of the methods in the TServiceManager class is void __fastcall RegisterServices(bool Install). However, this method is protected, which means we cannot get at it in a convenient way. How then do we arrive at that particular method? Now we need the source code of the runtime libraries, and I will demonstrate why it is so important to have such a resource in case you're in a tight spot. If necessary, you can always look at the code to deduce what you need to know. Anyway, the step from <vcl/SvcMgr.hpp> to SvcMgs.pas is a small one. That is the result of applying such small bits of useful knowledge: incorporating a pas-file in a project results in a hpp-header for use in the C++ stuff. Repetitive examinations finally lead to looking at the places where RegisterServices was called in that unit, and lo-and-behold; there was the little gem of power we needed! If you have your service application ready, execute it while appending the /INSTALL switch. Yes, slash-capital-I-N-S-T-A-L-L. If you gave the various design time properties the correct values, the generated executable will make the necessary modifications in the registry so that Windows NT can start your service from the Services control panel applet. What I also concluded was that the service executable can be uninstalled by appending the /UNINSTALL switch.
Do you have the power?
In order to install your service on a machine you must have administrative rights. You need those rights in order to be able to install, start and stop the service. If you do not have those rights, you can not do that, and you must ask your system administrator for it. And knowing that kind of people...
There are two properties in the TService component that I wish to criticize. They are ServiceStartName and Password. Since that can be pretty sensitive information, I would rather see that the RegisterServices was extended with two other switches that read that information from the command line. The usefulness of those two properties is a bit low, since the combination of account and password tends to differ from machine to machine. Also, a little bit of help when appending the I-don't-know-please-help when appending slash-question mark after the command line would help very much, not to mention a little piece of text in the online help!
While experimenting a little with the example that is in the help file about service applications, I noticed that my computer spent almost all its CPU cycles to that particular service. You must take into account that a service must not hog the computer too much. Especially, you might want to be careful about letting the service run long and intensive computations or tight polling loops of some sort or another. Another warning is that a service is running in supervisor mode. That means that it can do (almost) anything and that also means that it can do almost anything wrong. Writing a service requires a good deal of firewalling code and testing. Be warned.
I found it very amusing that this little bit of information about installing services was nowhere to be found in the online help of C++ Builder as well as Delphi. Clearly a minor but annoying oversight. On the other hand, the support for NT services in Delphi and C++ Builder is very useful. Besides, the method for installing and uninstalling services is the same for both development environments. Services are always running, even when all users are logged of. And of course, everybody is going to run off now to produce that last and ultimate killer service. Good luck!