一、Win2000服務簡介
服務程序(Service Application)是一種運行於WinNT的後台程序,每個服務 程序(Service Application)中可能包含若干個服務(Service),每個服務就 是其中的一個線程(該服務也可以創建多個子線程)。采用服務,應用程序可以 獲得特殊的權限,而且不會被用戶通過Win2000的任務管理器直接結束程序,所以 服務常常用來實現一些特殊的目標。
通過Win2000控制面板中的服務管理工具,我們可以設置/查看服務的特性:
(1)服務名稱;(2)顯示名稱;(3)描述;(4)啟動類型;(5)依賴關 系;
其中,服務名稱是標識給服務的。
以Win2000的C:\WINNT\System32\services.exe程序為例子,該Exe文件對應一個 Service Application,是該服務程序的可見實體;該exe中包含多個服務 (Service),例如Alerter,Dhcp(DHCP Client),Messenger等。當我們結束 一個服務的時候,該服務所在的Service Application中的其他服務並沒有被終止 。
在Delphi中,Borland的工程師為我們提供了TServiceApplication,TService ,TServiceThread等類,封裝了大量細節,簡化了服務程序的開發。
二、TServiceApplication
在Delphi中,類TServiceApplication就對應上述的ServiceApplication。利 用Delphi的開發環境,我們新建一個Service Application Project,同時就創建 了一個繼承自TService的類。項目文件中的Application對象就是一個 TServiceApplication實例。每個TServiceApplication包含若干個TService對象 ,正好對應上述的服務程序和服務之間的數量關系。
通過閱讀TServiceApplication和TService類的定義,可以得知, TServiceApplication從TComponent類繼承而來,TService從類TDataModule基礎 而來,Application對象負責各個TService對象的Create和Destroy。跟蹤下列代 碼
Application.CreateForm(TService1, Service1);
可以發現創建的TService對象的Owner都是Application對象;在VCL Framework中Owner總是負責Destroy各個Component對象(VCL的TComponent類采用 了Composite模式),所以TServiceApplication也將Destroy各個TService對象。
下面跟蹤TServiceApplication.Run的代碼,可以發現TServiceApplication首 先解析運行參數,實現了服務的Install和Uninstall。然後,初始化一個 ServiceStartTable數組,該數組包含了各個service對象的服務名稱和運行入口 ;最後創建一個TServiceStartThread 對象,該對象是一個線程對象,從線程調 用API:StartServiceCtrlDispatcher來啟動ServiceStartTable中指定的若干個 服務;而ServiceApplication主線程就不斷循環,處理消息,比如接收請求來停 止/暫停某個服務。
三、TService
TService類繼承自類 TDataModule,這意味著我們可以加入大量的VCL控件, 實現豐富的功能。此外,我們還可以處理OnStart,OnPause,OnStop, OnContinue,OnCreate,OnShutDown等事件。其中需要說明的是:OnStop表示該 服務被停止;而OnShutDown表示該ServiceApplication停止運行,這意味著其他 服務也被終止了;兩者含義是不一樣的。
前面講過,ServiceApplication通過調用StartServiceCtrlDispatcher來啟動 各個服務。StartServiceCtrlDispatcher啟動TService的入口,該入庫就是 TService.Main。TService.Main首先注冊該服務,然後調用TService.DoStart。 TService.DoStart創建一個內部TServiceThread成員對象,這是一個線程對象; 考察TServiceThread.Execute可以得知,當我們處理的TService1. OnExecute, 那麼TService會把所有的請求委托給該TServiceThread成員對象處理,該對象以 默認的方式處理所有的請求。
TService. ServiceExecute是TService的主體內容。一個服務要正常運行,除 了需要處理它要關注的目標(比如監聽某個端口、執行某個任務等)外,還要響 應外部命令/請求:比如終止、暫停、恢復該服務。因此可以考慮創建一個專門的 線程來完成該任務,而在ServiceExecute中處理外面命令/請求。因此代碼如下:
while not Terminated do begin
ServiceThread.ProcessRequests(False);
end;
當然,也可以在OnExecute中處理某些任務,如監聽某個端口,但是這常常會 導致該Service不能及時響應Stop/Pause等請求。當OnExecute執行完了,該服務 實際上就完成了任務要結束了(terminate)。