2013-08-06 6 views
8

Ich habe einige Windows-Dienste, die ich in Delphi geschrieben habe und sie arbeiten im Allgemeinen sehr gut, aber gelegentlich bekomme ich eine Ausnahme geworfen, die als fatal angesehen werden kann. Wenn dies geschieht, ist der Dienst zum Stoppen eingerichtet.Wie bekomme ich Windows SCM meinen Dienst neu zu starten, wenn es fehlschlägt

Meine Frage ist, wie kann ich den Dienst so beenden, dass der SCM automatisch versucht, den Dienst neu zu starten. (Ich habe bereits die Wiederherstellungsoptionen für den Dienst in den Dienst-Manager eingestellt)

MSDN Staaten

Ein Service betrachtet wird versagt, wenn es beendet wird, ohne den Status SERVICE_STOPPED an den Service Controller zu berichten.

Ich habe diesen Blogpost Using the Automatic Recovery Features of Windows Services gelesen, aber ich bin mir nicht sicher, wie dies in Delphi zu implementieren.

Ich habe versucht allready die folgenden

  • das ErrCode Eigentum der TService Einstellung auf einen Wert ungleich Null.
  • Einstellung des gestoppten Parameters des ServiceStop-Ereignisses auf false.
  • Eine Ausnahme im Servicestop-Event-Handler auslösen.

EDIT 2013.08.06 hinzugefügt Codebeispiel

-Code Jetzt

Hier wird der Code im mit,

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; 

Aktualisiert zeigen Beispiel Arbeits FFatalError ist ein privates boolesches Feld in der TTestService-Klasse und wird initialisiert auf false Beim Start wird nur true festgelegt, wenn der Arbeitsthread (der im TTestService.ServiceStart-Ereignis gestartet wurde) mit einer schwerwiegenden Ausnahme beendet wird.

Hier ist der OnTerminate-Ereignishandler für den Worker-Thread.

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; 
+0

Haben Sie versucht, 'ExitProcess' aufzurufen? –

+0

"Wenn dies passiert, ist der Dienst zum Stoppen eingerichtet." Das könnte das Problem sein.Möglicherweise müssen Sie wählen, ob Sie die Ausnahme behandeln oder wirklich fehlschlagen lassen möchten. Wenn Sie beispielsweise den Code posten, der den Dienst "stoppen" soll, können wir möglicherweise klarer sehen. – Sam

+0

Beenden Sie einfach den Serviceprozess über den Task-Manager. Wenn die SCM-Neustartkonfiguration für Ihren Dienst korrekt ist, wird der Dienst neu gestartet. – Alexandr

Antwort

8

Der SCM startet Ihren Dienst neu, wenn er fehlschlägt. Aber alle normalen Beendigungsmodi von einem Delphi-Dienst zählen nicht als Fehler. Wenn Sie eine Ausnahme vom Hauptdienstthread auslösen könnten, der nicht behandelt wurde, würde dies als Fehler gewertet werden.

Ich denke jedoch, der einfachste Weg für Sie, eine Prozessbeendigung zu erzwingen, die als Fehler behandelt wird, ist ExitProcess. Sie könnten genauso gut die Delphi RTL-Funktion Halt aufrufen, die letztendlich ExitProcess aufrufen wird. Da Ihr Prozess wahrscheinlich in einem schlechten Zustand ist, würde ich gerne direkt zu ExitProcess gehen.

Wie bereits erwähnt, wäre die Vermeidung der Ausnahme an erster Stelle die ideale Lösung.

+1

jitenable kann helfen. –

+0

Danke für Ihre Hilfe, ich habe das jetzt funktioniert und habe den Code in der Frage aktualisiert, um meine Lösung zu zeigen – MikeT

Verwandte Themen