2012-09-15 66 views
0

我想在Delphi中使服務應用程序每天運行並複製一些文件在下午2:00。所以我使用了計時器。但控制不會進入計時器事件並且服務在15秒內終止。我在Timer Event上寫了一段代碼。我如何使用計時器與服務?請幫忙。提前致謝。德爾福服務應用程序停止15秒後,定時器不執行

我的代碼是在這裏:

unit untMain; 

interface 

uses 
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Classes, Vcl.Graphics, 
Vcl.Controls, Vcl.SvcMgr, Vcl.Dialogs, Vcl.ExtCtrls, DateUtils, Vcl.Forms, 
untCommon; 

type 
TsrvBackupService = class(TService) 
tmrCopy: TTimer; 
procedure tmrCopyTimer(Sender: TObject); 

private 
strlstFiles : TStringList; 
{ Private declarations } 
public 
{ Public declarations } 
end; 

var 
srvBackupService: TsrvBackupService; 

implementation 

{$R *.DFM} 

procedure ServiceController(CtrlCode: DWord); stdcall; 
begin 
srvBackupService.Controller(CtrlCode); 
end; 


procedure TsrvBackupService.tmrCopyTimer(Sender: TObject); 
var 
strCurTime : string; 
strBKPpath : string; 
strBKPTime : string; 
NowDay  : word; 
NowMonth  : word; 
NowYear  : word; 
NowHour  : word; 
NowMin  : word; 
NowSec  : word; 
NowMilli  : Word; 
begin 
    DecodeTime(now,NowHour,NowMin,NowSec,NowMilli); 
    strCurTime := IntToStr(NowHour)+':'+IntToStr(NowMin); 
    strBKPTime := '14:00' 
    strBKPpath := ExtractFilePath(Application.ExeName); 
    if strCurTime = strBKPTime then begin 
    Try 
      CopyFile(PChar('c:\datafile.doc'),PChar(strBKPpath + 'datafile.doc'),true); 
    except 
     on l_e: exception do begin 
      MessageDlg(l_E.Message,mtError,[mbOk],0); 
     end; 
    end; 
    end; 
end; 

end. 
+2

請告訴我們你寫 –

+3

代碼你所描述不是定製的書面服務,但一個計劃的任務 –

回答

4

而不是一個計時器,使用的OnStart事件展開了簡單的線程。

的指南是在這裏:

http://www.tolderlund.eu/delphi/service/service.htm

TTimer更適合於GUI應用程序。他們需要一個消息泵(見here):

TTimer需要運行的消息隊列,以收到 WM_TIMER消息,允許OS將消息傳遞給HWND, 或觸發指定的回調

+3

大多數人不明白如何正確使用OnExecute事件,所以他們最終意外死鎖服務和/或導致有關該服務沒有響應的SCM錯誤,並想知道爲什麼。保持OnExecute事件未分配,並讓TService爲您管理SCM交互。使用OnStart事件創建工作線程的建議是最好的方法。 –

+1

^+1,正如我在這裏解釋的:http://stackoverflow.com/a/10538102/800214 – whosrdaddy

0

正如其他人所解釋的,你不能簡單地用一個TTimer組件Windows服務應用程序裏面,因爲它依賴於不以服務來默認消息泵。我看到四個主要選項:

  1. 實現一個message pump能夠使用TTimer
  2. 使用Thread爲日連續檢查/時間
  3. 就像#2,使用本服務的OnExecute event到檢查日期/時間
  4. 利用Windows的Scheduled Tasks

我會建議上述#2,和這裏的原因。

#1可能對你的情況有點多,我相信你不想走那麼遠。

#3可能會更容易,但服務的線程需要一點特殊的待遇,我也相信你不需要關心。

#4可能是理想的解決方案,但我不會嘗試改變您對服務的決定。

創建一個線程是要走的路,因爲它非常簡單和可擴展。我所有的服務應用程序都是在多線程的基礎上工作的,除了處理實際的服務之外,沒有任何東西進入實際服務的線程中。

我正在爲您準備一個樣本,但我過分複雜,將它包含在這裏會造成很多污染。我希望至少讓你朝着正確的方向前進。

+0

選項1真的很容易。選項2,你不是真的指「連續檢查」嗎?還是你提出睡眠和投票?仍然是一個相當卑鄙的選擇。 Windows中有定時器不需要消息泵。選項4是真正的答案! –

+0

我是delphi的新手,請使用'TTimer'向我展示代碼。 – Ganesh

+0

@Gani參考我上面發佈的鏈接,你可以在那裏找到代碼。 –

0

當你說「服務在15秒後終止」時,它讓我覺得你正在調試代碼。

如果您沒有任何選項並且無法使用他人建議的內容,則使用上面的代碼正確觸發計時器事件當您通過services.msc安裝並啓動服務時。但是,如果您正在調試服務,則不會觸發定時器事件,並且應用程序將終止(如您所述)。我想創建一個程序定時器事件中被調用,並調用它曾經在ServiceExecute事件,所以你可以調試這樣的:

procedure TSomeService.ServiceExecute(Sender: TService); 
begin 
    ExecuteSomeProcess(); // Put breakpoint here to debug 
    while not self.Terminated do 
    ServiceThread.ProcessRequests(true); 
end; 

procedure TSomeService.TimerTimer(Sender: TObject); 
begin 
    timer.Enabled := false; 
    ExecuteSomeProcess(); // This can't throw any exception! 
    timer.Enabled := true; 
end;