9

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;
4

1 に答える 1