Dienststeuerungshandler-Funktion
Jeder Dienst verfügt über einen Steuerelementhandler, die Handler-Funktion , die vom Steuerelementverteiler aufgerufen wird, wenn der Dienstprozess eine Steuerungsanforderung von einem Dienststeuerungsprogramm empfängt. Daher wird diese Funktion im Kontext des Steuerelementverteilers ausgeführt. Ein Beispiel finden Sie unter Schreiben einer Steuerelementhandlerfunktion.
Ein Dienst ruft die Funktion RegisterServiceCtrlHandler oder RegisterServiceCtrlHandlerEx auf, um seine Dienststeuerungshandlerfunktion zu registrieren.
Wenn der Dienststeuerungshandler aufgerufen wird, muss der Dienst die Funktion SetServiceStatus aufrufen, um seine status nur dann an den SCM zu melden, wenn die Behandlung des Steuerelementcodes dazu führt, dass sich der Dienst status ändert. Wenn die Verarbeitung des Steuerelementcodes nicht dazu führt, dass sich der status des Diensts ändert, ist es nicht erforderlich, SetServiceStatus aufzurufen.
Ein Dienststeuerungsprogramm kann Steuerungsanforderungen mithilfe der ControlService-Funktion senden. Alle Dienste müssen den SERVICE_CONTROL_INTERROGATE-Steuerungscode akzeptieren und verarbeiten. Sie können die Akzeptanz der anderen Steuercodes aktivieren oder deaktivieren, indem Sie SetServiceStatus aufrufen. Um den SERVICE_CONTROL_DEVICEEVENT-Steuerelementcode zu erhalten, müssen Sie die Funktion RegisterDeviceNotification aufrufen. Dienste können auch zusätzliche benutzerdefinierte Steuercodes verarbeiten.
Wenn ein Dienst den SERVICE_CONTROL_STOP-Steuerelementcode akzeptiert, muss er beim Empfang beendet werden und wechselt entweder zum SERVICE_STOP_PENDING oder SERVICE_STOPPED Zustand. Nachdem der SCM diesen Steuerungscode gesendet hat, werden keine weiteren Steuerelementcodes gesendet.
Windows XP: Wenn der Dienst NO_ERROR zurückgibt und weiterhin ausgeführt wird, empfängt er weiterhin Steuerungscodes. Dieses Verhalten hat sich ab Windows Server 2003 und Windows XP mit Service Pack 2 (SP2) geändert.
Der Steuerelementhandler muss innerhalb von 30 Sekunden zurückgegeben werden, oder der SCM gibt einen Fehler zurück. Wenn ein Dienst eine langwierige Verarbeitung durchführen muss, wenn der Dienst den Steuerelementhandler ausführt, sollte er einen sekundären Thread erstellen, um die langwierige Verarbeitung auszuführen, und dann vom Steuerelementhandler zurückgegeben wird. Dadurch wird verhindert, dass der Dienst den Kontrollverteiler bindet. Wenn Sie z. B. die Beendigungsanforderung für einen Dienst behandeln, der lange dauert, erstellen Sie einen weiteren Thread, um den Stoppprozess zu behandeln. Der Steuerelementhandler sollte einfach SetServiceStatus mit der SERVICE_STOP_PENDING-Nachricht aufrufen und zurückgeben.
Wenn der Benutzer das System herunterfährt, erhalten alle Steuerelementhandler, die SetServiceStatus mit dem SERVICE_ACCEPT_PRESHUTDOWN-Steuerelementcode aufgerufen haben, den SERVICE_CONTROL_PRESHUTDOWN-Steuerelementcode . Der Dienststeuerungs-Manager wartet, bis der Dienst beendet wird oder bis der angegebene Preshutdown-Timeoutwert abläuft (dieser Wert kann mit der ChangeServiceConfig2-Funktion festgelegt werden). Dieser Steuerungscode sollte nur unter besonderen Umständen verwendet werden, da ein Dienst, der diese Benachrichtigung verarbeitet, das Herunterfahren des Systems blockiert, bis der Dienst beendet wird oder das Timeoutintervall für den Preshutdown abläuft.
Nachdem die Vorabbenachrichtigungen abgeschlossen wurden, erhalten alle Steuerelementhandler, die SetServiceStatus mit dem SERVICE_ACCEPT_SHUTDOWN-Steuerelementcode aufgerufen haben, den SERVICE_CONTROL_SHUTDOWN-Steuerelementcode. Sie werden in der Reihenfolge benachrichtigt, in der sie in der Datenbank der installierten Dienste angezeigt werden. Standardmäßig hat ein Dienst etwa 20 Sekunden Zeit, um Bereinigungsaufgaben auszuführen, bevor das System heruntergefahren wird. Nach Ablauf dieser Zeit wird das Herunterfahren des Systems unabhängig davon fortgesetzt, ob das Herunterfahren des Diensts abgeschlossen ist. Beachten Sie, dass der Dienst weiterhin ausgeführt wird, wenn sich das System im Zustand "Herunterfahren" befindet (nicht neu gestartet oder heruntergefahren).
Wenn der Dienst mehr Zeit zum Bereinigen benötigt, sendet er STOP_PENDING status Nachrichten zusammen mit einem Wartehinweis, damit der Dienstcontroller weiß, wie lange er warten muss, bevor er an das System meldet, dass das Herunterfahren des Diensts abgeschlossen ist. Um jedoch zu verhindern, dass ein Dienst das Herunterfahren beendet, gibt es eine Beschränkung für die Wartezeit des Dienstcontrollers. Wenn der Dienst über das Dienste-Snap-In heruntergefahren wird, beträgt der Grenzwert 125 Sekunden oder 125.000 Millisekunden. Wenn das Betriebssystem neu gestartet wird, wird das Zeitlimit im WaitToKillServiceTimeout-Wert (in Millisekunden) des folgenden Registrierungsschlüssels angegeben:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control
Wichtig
Ein Dienst sollte nicht versuchen, das Zeitlimit durch Ändern dieses Werts zu erhöhen. Wenn Sie WaitToKillServiceTimeout manuell festlegen müssen, sollte der Wert in Millisekunden angegeben werden.
Kunden benötigen ein schnelles Herunterfahren des Betriebssystems. Wenn beispielsweise ein Computer mit USV-Strom nicht vollständig heruntergefahren werden kann, bevor die USV die Stromversorgung ausgeht, können Daten verloren gehen. Daher sollten Dienste ihre Bereinigungsaufgaben so schnell wie möglich erledigen. Es empfiehlt sich, nicht gespeicherte Daten zu minimieren, indem Daten regelmäßig gespeichert werden, die Daten, die auf dem Datenträger gespeichert werden, nachverfolgt werden, und ihre nicht gespeicherten Daten nur beim Herunterfahren gespeichert werden. Da der Computer heruntergefahren wird, sollten Sie keine Zeit damit verbringen, zugewiesenen Arbeitsspeicher oder andere Systemressourcen freizugeben. Wenn Sie einen Server benachrichtigen müssen, den Sie beenden, minimieren Sie die Wartezeit auf eine Antwort, da Netzwerkprobleme das Herunterfahren Ihres Diensts verzögern können.
Beachten Sie, dass der SCM beim Herunterfahren des Diensts standardmäßig keine Abhängigkeiten berücksichtigt. Der SCM listet die Liste der ausgeführten Dienste auf und sendet den befehl SERVICE_CONTROL_SHUTDOWN . Daher kann ein Dienst fehlschlagen, weil ein anderer Dienst, von dem er abhängig ist, bereits beendet wurde.
Um die Reihenfolge des Herunterfahrens von Diensten manuell festzulegen, erstellen Sie einen Registrierungswert mit mehreren Zeichenfolgen, der die Dienstnamen in der Reihenfolge enthält, in der sie heruntergefahren werden sollen, und weisen Sie ihn dem Wert PreshutdownOrder des Control-Schlüssels wie folgt zu:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\PreshutdownOrder="Shutdown Order"
Verwenden Sie die SetProcessShutdownParameters-Funktion , um die Reihenfolge des Herunterfahrens abhängiger Dienste aus Ihrer Anwendung festzulegen. Der SCM verwendet diese Funktion, um seinem Handler 0x1E0 Priorität zu geben. Der SCM sendet SERVICE_CONTROL_SHUTDOWN Benachrichtigungen, wenn sein Steuerelementhandler aufgerufen wird, und wartet, bis die Dienste beendet werden, bevor er von seinem Steuerelementhandler zurückkehrt.
Zugehörige Themen