Delphi で記述した Windows サービスがいくつかあり、通常は非常にうまく機能しますが、致命的と見なされる例外がスローされることがあります。これが発生すると、サービスは停止するように設計されています。
私の質問は、SCM が自動的にサービスを再起動しようとするような方法でサービスを終了する方法です。(サービスマネージャーでサービスの回復オプションを既に設定しています)
MSDNの状態
SERVICE_STOPPED のステータスをサービス コントローラに報告せずにサービスが終了すると、サービスは失敗したと見なされます。
Windows サービスの自動回復機能を使用したこのブログ投稿を読みましたが、デルファイでこれを実装する方法がわかりません。
私はすでに次のことを試しました
- TService の ErrCode プロパティをゼロ以外の値に設定します。
- ServiceStop イベントの stopped パラメータを false に設定します。
- servicestop イベント ハンドラーで例外を発生させます。
EDIT 2013-08-06 コード例を追加
動作例を示すためにコードが更新されました
これが私が使用しているコードです、
procedure TTestService.ServiceExecute(Sender: TService);
begin
while not (Terminated or FFatalError) do
begin
ServiceThread.ProcessRequests(False);
ReportStatus;
Sleep(100);
end;
if FFatalError then
Halt(1);
end;
FFatalError は、TTestService クラスのプライベート ブール フィールドであり、起動時に false に初期化されます。これは、(TTestService.ServiceStart イベントで開始された) ワーカー スレッドが致命的な例外で終了した場合にのみ、true に設定されます。
これは、ワーカー スレッドの OnTerminate イベント ハンドラです。
procedure TTestService.ThdTerm(Sender: Tobject);
var
E : Exception;
Thread : TThread;
begin
Thread := TThread(Sender);
if (Thread.FatalException <> nil) then
begin
E := Exception(Thread.FatalException);
GetExcCallStack(E);
EventLog.LogError(Thread.ClassName + ': ID:'+ IntToStr(Thread.ThreadID) +
' Stopped Unexpectedly!, '+ NEWLINE + E.ClassName +': ' + E.Message);
FFatalError := True;
end;
end;