Freigeben über


Dienststeuerungshandlerfunktion

Jeder Dienst verfügt über einen Steuerelementhandler, den Handler-Funktion, der vom Steuerelementverteilungsdienst aufgerufen wird, wenn der Dienstprozess eine Steuerelementanforderung von einem Dienststeuerungsprogramm empfängt. Daher wird diese Funktion im Kontext des Steuerelement-Dispatchers ausgeführt. Ein Beispiel finden Sie unter Schreiben einer Steuerelementhandlerfunktion.

Ein Dienst ruft den RegisterServiceCtrlHandler oder RegisterServiceCtrlHandlerEx--Funktion auf, um seine Dienststeuerungshandlerfunktion zu registrieren.

Wenn der Dienststeuerungshandler aufgerufen wird, muss der Dienst die SetServiceStatus--Funktion aufrufen, um den Status nur dann beim SCM zu melden, wenn der Steuerelementcode den Dienststatus ändert. Wenn das Behandeln des Steuerelementcodes nicht dazu führt, dass sich der Dienststatus ändert, ist es nicht erforderlich, SetServiceStatus-aufzurufen.

Ein Dienststeuerungsprogramm kann Steuerelementanforderungen mithilfe der ControlService--Funktion senden. Alle Dienste müssen den SERVICE_CONTROL_INTERROGATE Steuercode akzeptieren und verarbeiten. Sie können die Annahme der anderen Steuercodes aktivieren oder deaktivieren, indem Sie SetServiceStatus-aufrufen. Um den SERVICE_CONTROL_DEVICEEVENT-Steuerelementcode zu erhalten, müssen Sie die RegisterDeviceNotification--Funktion aufrufen. Dienste können auch zusätzliche benutzerdefinierte Steuerelementcodes verarbeiten.

Wenn ein Dienst den SERVICE_CONTROL_STOP-Steuerelementcode akzeptiert, muss er nach Erhalt beendet werden, entweder zum SERVICE_STOP_PENDING oder SERVICE_STOPPED Zustand. Nachdem der SCM diesen Steuerelementcode gesendet hat, sendet es keine anderen Steuerelementcodes.

Windows XP: Wenn der Dienst NO_ERROR zurückgibt und weiterhin ausgeführt wird, empfängt er weiterhin Steuercodes. Dieses Verhalten wurde ab Windows Server 2003 und Windows XP mit Service Pack 2 (SP2) geändert.

Der Steuerelementhandler muss innerhalb von 30 Sekunden zurückgeben, oder der SCM gibt einen Fehler zurück. Wenn ein Dienst eine lange Verarbeitung ausführen muss, wenn der Dienst den Steuerelementhandler ausführt, sollte ein sekundärer Thread erstellt werden, um die langwierige Verarbeitung durchzuführen und dann vom Steuerelementhandler zurückzugeben. Dadurch wird verhindert, dass der Dienst den Kontrollteiler bindet. Wenn Sie beispielsweise die Stop-Anforderung für einen Dienst behandeln, der lange dauert, erstellen Sie einen anderen Thread, um den Stoppvorgang zu verarbeiten. Der Steuerelementhandler sollte einfach SetServiceStatus- mit der SERVICE_STOP_PENDING Nachricht aufrufen und zurückgeben.

Wenn der Benutzer das System heruntergefahren hat, 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 der angegebene Preshutdown-Timeoutwert abläuft (dieser Wert kann mit der funktion ChangeServiceConfig2 festgelegt werden). Dieser Steuerelementcode sollte nur unter besonderen Umständen verwendet werden, da ein Dienst, der dieses Benachrichtigungs-System heruntergefahren, blockiert, bis der Dienst beendet wird oder das Vorabtimeoutintervall 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 ca. 20 Sekunden Zeit, um Bereinigungsaufgaben auszuführen, bevor das System heruntergefahren wird. Nach Ablauf dieses Zeitraums wird das Herunterfahren des Systems fortgesetzt, unabhängig davon, ob das Herunterfahren des Diensts abgeschlossen ist. Beachten Sie, dass der Dienst weiterhin ausgeführt wird, wenn das System im Zustand "Herunterfahren" (nicht neu gestartet oder heruntergefahren) verbleibt.

Wenn der Dienst mehr Zeit zum Bereinigen benötigt, sendet er STOP_PENDING Statusmeldungen zusammen mit einem Wartehinweis, sodass der Dienstcontroller weiß, wie lange gewartet werden muss, bevor das System gemeldet wird, dass das Herunterfahren des Diensts abgeschlossen ist. Um jedoch zu verhindern, dass ein Dienst heruntergefahren wird, gibt es eine Beschränkung, wie lange der Servicecontroller wartet. Wenn der Dienst über das Services-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 zu erhöhen, indem er diesen Wert ändert. Wenn Sie WaitToKillServiceTimeout- manuell festlegen müssen, sollte der Wert in Millisekunden angegeben werden.

Kunden benötigen ein schnelles Herunterfahren des Betriebssystems. Wenn z. B. ein Computer, der auf USV-Strom ausgeführt wird, das Herunterfahren nicht abschließen kann, bevor der STROM ausgeht, können Daten verloren gehen. Daher sollten Dienste ihre Bereinigungsaufgaben so schnell wie möglich abschließen. Es empfiehlt sich, nicht gespeicherte Daten zu minimieren, indem Sie Daten regelmäßig speichern, die auf dem Datenträger gespeicherten Daten nachverfolgen und nur ihre nicht gespeicherten Daten beim Herunterfahren speichern. Da der Computer heruntergefahren wird, verbringen Sie keine Zeit damit, zugeordneten Arbeitsspeicher oder andere Systemressourcen freizugeben. Wenn Sie einen Server benachrichtigen müssen, den Sie beenden, minimieren Sie die Zeit, die auf eine Antwort gewartet hat, da Netzwerkprobleme das Herunterfahren Ihres Diensts verzögern können.

Beachten Sie, dass beim Herunterfahren des Diensts standardmäßig keine Abhängigkeiten berücksichtigt werden. Der SCM listet die Liste der ausgeführten Dienste auf und sendet den befehl SERVICE_CONTROL_SHUTDOWN. Daher kann ein Dienst fehlschlagen, da ein anderer Dienst, von dem er abhängt, 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 PreshutdownOrder Wert des Steuerelementschlü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 von Ihrer Anwendung festzulegen. Der SCM verwendet diese Funktion, um dem 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 sie vom Steuerelementhandler zurückgegeben werden.

Schreiben einer Steuerelementhandlerfunktion