Windows的服務是一個比較實用的功能,你的程式可以在Windows未進行登入的時候就開始運行,不受使用者登出的影響,也不容易被使用者誤關閉。 但是編寫服務也許不是一件容易的事情,幸好Delphi給我們提供了一個模板,可以很容易的編寫一個標準的Windows服務程式。 首先,在Delphi內建立一個Service Application。 此時,Delphi已經給我們建好了一個Service程式的架構,我們只需要把我們的代碼加到合適的位置就行了。 一般情況下,Service內需要一個線程來不斷的工作,也許定時器也可以,但線程工作起來更好。 Delphi會產生一個可視化的Service容器,你可以一些必要的控制項在它上面,但是由於它是服務程式,是沒有介面顯示的,因此不建議在上面安放Edit之類的控制項,服務只是應該做處理工作的,顯示介面應該由其它的程式來完成。Service控制項的DisplayName屬性是顯示在管理工具-》服務的左邊的名稱的內容,而Name屬性則是服務名稱,當你用命令提示字元來啟動、停止服務時,就需要用到。 在事件OnStart內,我們應該完成啟動線程的工作。 如: procedure TS2HConv.ServiceStart(Sender: TService; var Started: Boolean); var Reg:TRegistry; LogFileName,LogPath:String; slTemp:TStringList; begin CoInitialize(nil); Reg:=TRegistry.Create; Reg.RootKey:=HKEY_LOCAL_MACHINE; Reg.OpenKey('/SoftWare/BHome/Education',True); LogPath:=Trim(Reg.ReadString('LogPath')); SourceConnStr:=Trim(Reg.ReadString('SourceConnStr')); if Trim(LogPath)='' then LogPath:='C:/'; Reg.CloseKey; Reg.Free; if RightStr(LogPath,1)<>'/' then LogPath:=LogPath+'/'; LogFileName:=LogPath+FormatDateTime('yyyymmdd',Now)+'Log.txt'; Try if not FileExists(LogFileName) then begin slTemp:=TStringList.Create; slTemp.Clear; slTemp.SaveToFile(LogFileName); slTemp.Free; end; AssignFile(LogFile, LogFileName); Append(LogFile); Except Started:=False; Exit; End; Started:=True; try AC_Source:=TADOConnection.Create(nil); Q_Source:=TADOQuery.Create(nil) ; Q_Source.Connection:=AC_Source; try AC_Source.Close; AC_Source.ConnectionString:=SourceConnStr; AC_Source.Open; SYSLog('與來源資料庫串連成功!'); DBOK:=True; Except on E:Exception do begin DBOK:=False; SYSLog('資料庫連接失敗!'+E.Message); end; End; MyPHSThread := TPHSSendThread.Create(); MyPHSThread.FreeOnTerminate:=True; MyPHSThread.Priority:= tpLower ; end; 在OnStop事件內,我們應該停止線程,並釋放開啟的資源,需要注意的是當你停止線程時,一般用Terminate方法,線上程內用Terminated屬性來判斷是否需要結束線程,而由於是線程,和主進程是時間啟動並執行,有可能你剛好在進行Terminate時,線程已經剛進行過Terminated判斷,進行中比較費時的處理工作,而此時主進程立即執行Terminate後就進行釋放資源的工作時,會造成線程執行錯誤,因此應該等到線程真正的正確停止後,主進程才能進行資源釋放工作。 如: procedure TS2HConv.ServiceStop(Sender: TService; var Stopped: Boolean); begin try MyPHSThread.Terminate; while __ThreadIsRun do sleep(1000); AC_Source.Close; CloseFile(LogFile); FreeAndNil(Q_Source); FreeAndNil(AC_Source); CoUnInitialize; Except End; Stopped:=True; end; |