delphi服务应用程序在15秒后停止,计时器未执行



我想在Delphi中制作一个服务应用程序,每天下午02:00运行并复制一些文件。所以我使用了定时器。但是控制不进入定时器事件,并且服务在15秒内终止。我写了一个关于Timer Event的代码。如何将计时器与服务一起使用?请帮忙。提前感谢。

我的代码在这里:

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.

使用在OnStart事件中启动的简单线程而不是计时器。

这里有一个教程:

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

TTimer更适合GUI应用程序。他们需要一个信息泵(见此处):

TTimer需要一个正在运行的消息队列才能接收WM_ TIMER消息,其允许OS将该消息传递给HWND,或触发指定的回调

正如其他人所解释的,您不能简单地在Windows服务应用程序中使用TTimer组件,因为它依赖于服务中默认不存在的消息泵。我看到四个主要选项:

  1. 实现一个能够使用CCD_ 2的消息泵
  2. 使用线程连续检查日期/时间
  3. 就像#2一样,使用服务的OnExecute事件检查日期/时间
  4. 利用Windows的计划任务

我推荐上面的#2,原因如下。

#1可能有点太适合你的场景了,我相信你不想走那么远。

#3可能更容易,但服务的线程需要一点特殊处理,我也相信你不需要关心。

#4可能是理想的解决方案,但我不会试图改变您对服务的决定。

创建一个线程是可行的,因为它非常简单且可扩展。我所有的服务应用程序都是在多线程的基础上工作的,除了处理实际的服务之外,任何东西都不会进入实际服务的线程。

我正在为你做一个样本,但我把它弄得太复杂了,把它包括在这里会有很多污染。我希望至少我让你朝着正确的方向前进。

当您说"服务在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;

最新更新