1

毎日午後 2 時にいくつかのファイルを実行してコピーするサービス アプリケーションを Delphi で作成したいと考えています。だから私はタイマーを使いました。しかし、制御はタイマー イベントに移行せず、サービスは 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.
4

3 に答える 3

6

タイマーの代わりに、OnStart イベントで起動される単純なスレッドを使用します。

チュートリアルはこちら:

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

TTimer は、GUI アプリケーションにより適しています。メッセージ ポンプが必要です (こちらを参照)。

TTimer は、OS がメッセージを HWND に渡すことを可能にする WM_TIMER メッセージを受信するため、または指定されたコールバックをトリガーするために、実行中のメッセージ キューを必要とします。

于 2012-09-15T12:27:11.380 に答える
1

「サービスは 15 秒後に終了します」と言うと、コードをデバッグしていると思われます。

オプションがなく、他の人が提案したものを使用できない場合は、services.msc を介してサービスをインストールして開始すると、タイマーイベントの上のコードが適切にトリガーされます。ただし、サービスをデバッグしている場合、タイマー イベントはトリガーされず、アプリケーションは終了します (前述のとおり)。タイマー イベント内で呼び出されるプロシージャを作成し、それを ServiceExecute イベントで 1 回呼び出すと、次のようにデバッグできます。

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;
于 2015-02-23T13:12:06.813 に答える
1

他の人が説明したようにTTimer、Windows サービス アプリケーション内で単純にコンポーネントを使用することはできません。これは、デフォルトではサービスに含まれていないメッセージ ポンプに依存しているためです。主なオプションは次の 4 つです。

  1. を使用できるようにメッセージ ポンプを実装しますTTimer
  2. スレッドを使用して、日付/時刻を継続的にチェックします
  3. #2と同様に、サービスのOnExecuteイベントを使用して日付/時刻を確認します
  4. Windows のスケジュールされたタスクを利用する

上記の#2をお勧めします。その理由は次のとおりです。

#1はあなたのシナリオには少し多すぎるかもしれませんが、そこまで行きたくないでしょう。

#3の方が簡単かもしれませんが、サービスのスレッドには少し特別な処理が必要ですが、気にする必要はないと確信しています。

#4 は理想的な解決策かもしれませんが、サービスに関する決定を変更しようとはしません。

スレッドを作成する方法は、かなり単純で拡張可能であるためです。私のサービス アプリケーションはすべてマルチスレッド ベースで動作し、実際のサービスを処理する以外に、実際のサービスのスレッド内には何も入りません。

私はあなたのためにサンプルを作成していましたが、複雑すぎて、ここに含めるのは大変なことになりました。少なくとも私があなたを正しい方向に動かせたことを願っています。

于 2012-09-17T09:50:30.037 に答える