Writing Win2000 service program using Delphi
Abstract: This article introduces the use of Delphi to write Win2000 service programs. The classes involved are TServiceApplicatoin, TService, TServiceThread, etc.
Keywords: Service/service
1. Introduction to Win2000 services
Service application is a background program running on WinNT. Each service application may contain several services, and each service is one of the threads (the service can also create multiple sub-services). thread). By using services, applications can obtain special permissions, and the user will not directly end the program through the Win2000 Task Manager, so services are often used to achieve some special goals.
Through the service management tool in the Win2000 control panel, we can set/view the characteristics of the service:
(1) Service name; (2) Display name; (3) Description; (4) Startup type; (5) Dependencies;
Among them, the service name identifies the service.
Take the C:/WINNT/System32/services.exe program of Win2000 as an example. This Exe file corresponds to a Service Application and is the visible entity of the service program; the exe contains multiple services (Service), such as Alerter, Dhcp (DHCP) Client), Messenger, etc. When we end a service, other services in the Service Application where the service is located are not terminated.
In Delphi, Borland engineers provide us with TServiceApplication, TService, TServiceThread and other classes, which encapsulate a large number of details and simplify the development of service programs.
2. TServiceApplication
In Delphi, the class TServiceApplication corresponds to the above-mentioned ServiceApplication. Using the Delphi development environment, we create a new Service Application PRoject and create a class inherited from TService. The Application object in the project file is a TServiceApplication instance. Each TServiceApplication contains several TService objects, which exactly correspond to the above-mentioned quantitative relationship between service programs and services.
By reading the definitions of TServiceApplication and TService classes, we can know that TServiceApplication inherits from the TComponent class, TService comes from the class TDataModule, and the Application object is responsible for the Create and Destroy of each TService object. Track the code below
Application.CreateForm(TService1, Service1);
It can be found that the owners of the created TService objects are all Application objects; in VCL FrameWork, the Owner is always responsible for destroying each Component object (VCL's TComponent class adopts the Composite mode), so TServiceApplication will also Destroy each TService object.
Following the code of TServiceApplication.Run, you can find that TServiceApplication first parses the running parameters and implements the Install and Uninstall of the service. Then, initialize a ServiceStartTable array, which contains the service name and running entry of each service object; finally create a TServiceStartThread object, which is a thread object, and call the API: StartServiceCtrlDispatcher from the thread to start several services specified in the ServiceStartTable; The ServiceApplication main thread keeps looping and processing messages, such as receiving requests to stop/pause a service.
3. TService
The TService class inherits from the TDataModule class, which means that we can add a large number of VCL controls to achieve rich functions. In addition, we can also handle OnStart, OnPause, OnStop, OnContinue, OnCreate, OnShutDown and other events. What needs to be explained is: OnStop means that the service has been stopped; and OnShutDown means that the ServiceApplication has stopped running, which means that other services have also been terminated; the meanings of the two are different.
As mentioned earlier, ServiceApplication starts each service by calling StartServiceCtrlDispatcher. StartServiceCtrlDispatcher starts the entrance of TService, which is TService.Main. TService.Main first registers the service and then calls TService.DoStart. TService.DoStart creates an internal TServiceThread member object, which is a thread object; examining TServiceThread.Execute, we can know that when we process TService1.OnExecute, then TService will delegate all requests to the TServiceThread member object for processing. The object starts with The default method handles all requests.
TService. ServiceExecute is the main content of TService. For a service to run normally, in addition to dealing with the goals it needs to focus on (such as listening to a certain port, performing a certain task, etc.), it also needs to respond to external commands/requests: such as terminating, pausing, and resuming the service. Therefore, you can consider creating a dedicated thread to complete this task and handle external commands/requests in ServiceExecute. So the code is as follows:
while not Terminated do begin
ServiceThread.ProcessRequests(False);
end;
Of course, you can also handle certain tasks in OnExecute, such as listening to a certain port, but this often results in the Service not being able to respond to Stop/Pause and other requests in a timely manner. When OnExecute is completed, the service has actually completed its task and is about to end (terminate).
References:
MSDN, Delphi VCL source code, Delphi help documentation