我想在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.
答案 0 :(得分:6)
使用在OnStart事件中启动的简单线程,而不是计时器。
教程在这里:
http://www.tolderlund.eu/delphi/service/service.htm
TTimer更适合GUI应用程序。他们需要一个消息泵(参见here):
TTimer需要一个正在运行的消息队列才能接收 WM_TIMER消息,允许操作系统将消息传递给HWND, 或触发指定的回调
答案 1 :(得分:1)
正如其他人所解释的那样,你不能简单地在Windows服务应用程序中使用TTimer
组件,因为它依赖于默认情况下在服务中没有出现的消息泵。我看到四个主要选择:
TTimer
,OnExecute
event检查日期/时间我会推荐上面的#2,这就是原因。
#1对你的场景可能有点多,我相信你不想走那么远。
#3可能更容易,但服务的线程需要一些特殊的处理,我也确定你不需要关心。
#4可能是理想的解决方案,但我不会尝试更改您对服务的决定。
创建线程是一种可行的方法,因为它非常简单且可扩展。我的所有服务应用程序都在多线程的基础上工作,除了处理实际服务之外,什么都没有进入实际服务的线程。
我正在为你准备一个样品,但是我过度复杂了,将它包含在这里会有很多污染。我希望至少我让你朝着正确的方向前进。
答案 2 :(得分:1)
当你说“服务在15秒后终止”时,我认为你正在调试代码。
如果您没有任何选项且无法使用其他人建议的内容,则使用上面的代码,当您通过services.msc 安装和启动服务时,会正确触发计时器事件。但是,如果您正在调试服务,则不会触发计时器事件 ,并且应用程序将终止(如您所述)。我会创建一个在timer事件中调用的过程,并在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;