Partager via


Fonction gestionnaire de contrôle de service

Chaque service a un gestionnaire de contrôles, la fonction gestionnaire, appelée par le répartiteur de contrôle lorsque le processus de service reçoit une demande de contrôle d’un programme de contrôle de service. Par conséquent, cette fonction s’exécute dans le contexte du répartiteur de contrôle. Pour obtenir un exemple, consultez Écriture d’une fonction de gestionnaire de contrôles.

Un service appelle la fonction RegisterServiceCtrlHandler ou RegisterServiceCtrlHandlerEx pour inscrire sa fonction de gestionnaire de contrôle de service.

Lorsque le gestionnaire de contrôle de service est appelé, le service doit appeler la fonction SetServiceStatus pour signaler son état au SCM uniquement si la gestion du code de contrôle entraîne la modification de l’état du service. Si la gestion du code de contrôle n’entraîne pas la modification de l’état du service, il n’est pas nécessaire d’appeler SetServiceStatus.

Un programme de contrôle de service peut envoyer des demandes de contrôle à l’aide de la fonctionControlService. Tous les services doivent accepter et traiter le code de contrôle SERVICE_CONTROL_INTERROGATE. Vous pouvez activer ou désactiver l’acceptation des autres codes de contrôle en appelant SetServiceStatus. Pour recevoir le code de contrôle SERVICE_CONTROL_DEVICEEVENT, vous devez appeler la fonction RegisterDeviceNotification. Les services peuvent également gérer des codes de contrôle définis par l’utilisateur supplémentaires.

Si un service accepte le code de contrôle SERVICE_CONTROL_STOP, il doit s’arrêter lors de la réception, en accédant à l’état SERVICE_STOP_PENDING ou SERVICE_STOPPED. Une fois que le SCM envoie ce code de contrôle, il n’envoie pas d’autres codes de contrôle.

Windows XP : Si le service retourne NO_ERROR et continue à s’exécuter, il continue de recevoir des codes de contrôle. Ce comportement a changé à partir de Windows Server 2003 et Windows XP avec Service Pack 2 (SP2).

Le gestionnaire de contrôle doit retourner dans un délai de 30 secondes, ou le gestionnaire de configuration de contrôle retourne une erreur. Si un service doit effectuer un traitement long lorsque le service exécute le gestionnaire de contrôles, il doit créer un thread secondaire pour effectuer le traitement long, puis retourner à partir du gestionnaire de contrôle. Cela empêche le service d’attacher le répartiteur de contrôle. Par exemple, lors de la gestion de la demande d’arrêt d’un service qui prend beaucoup de temps, créez un autre thread pour gérer le processus d’arrêt. Le gestionnaire de contrôle doit simplement appeler SetServiceStatus avec le message SERVICE_STOP_PENDING et retourner.

Lorsque l’utilisateur arrête le système, tous les gestionnaires de contrôle qui ont appelé SetServiceStatus avec le code de contrôle SERVICE_ACCEPT_PRESHUTDOWN reçoivent le code de contrôle SERVICE_CONTROL_PRESHUTDOWN. Le gestionnaire de contrôle de service attend que le service s’arrête ou que la valeur de délai d’attente de préshutdown spécifiée expire (cette valeur peut être définie avec la fonction ChangeServiceConfig2). Ce code de contrôle ne doit être utilisé que dans des circonstances particulières, car un service qui gère cet arrêt du système bloque l’arrêt du système jusqu’à ce que le service s’arrête ou que l’intervalle de délai d’expiration du délai d’attente avant expiration.

Une fois les notifications prédéfinies terminées, tous les gestionnaires de contrôle qui ont appelé SetServiceStatus avec le code de contrôle SERVICE_ACCEPT_SHUTDOWN reçoivent le code de contrôle SERVICE_CONTROL_SHUTDOWN. Ils sont avertis dans l’ordre dans lequel ils apparaissent dans la base de données des services installés. Par défaut, un service a environ 20 secondes pour effectuer des tâches de nettoyage avant l’arrêt du système. Une fois cette période expirée, l’arrêt du système se poursuit, que l’arrêt du service soit terminé. Notez que si le système est laissé dans l’état d’arrêt (non redémarré ou sous tension), le service continue à s’exécuter.

Si le service nécessite plus de temps pour nettoyer, il envoie des messages d’état STOP_PENDING, ainsi qu’un indicateur d’attente, afin que le contrôleur de service sache combien de temps attendre avant de signaler au système que l’arrêt du service est terminé. Toutefois, pour empêcher un service d’arrêter l’arrêt, il existe une limite à la durée pendant laquelle le contrôleur de service attend. Si le service est arrêté via le composant logiciel enfichable Services, la limite est de 125 secondes ou de 125 000 millisecondes. Si le système d’exploitation redémarre, la limite de temps est spécifiée dans la WaitToKillServiceTimeout valeur (en millisecondes) de la clé de Registre suivante :

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control

Important

Un service ne doit pas tenter d’augmenter la limite de temps en modifiant cette valeur. Si vous devez définir WaitToKillServiceTimeout manuellement, la valeur doit être en millisecondes.

Les clients nécessitent un arrêt rapide du système d’exploitation. Par exemple, si un ordinateur en cours d’exécution sur l’alimentation UPS ne peut pas se terminer avant l’arrêt de l’UPS, les données peuvent être perdues. Par conséquent, les services doivent effectuer leurs tâches de nettoyage le plus rapidement possible. Il est recommandé de réduire les données non enregistrées en enregistrant régulièrement des données, en conservant le suivi des données enregistrées sur le disque et enregistrant uniquement vos données non enregistrées lors de l’arrêt. Étant donné que l’ordinateur est arrêté, ne passez pas de temps à libérer de la mémoire allouée ou d’autres ressources système. Si vous devez avertir un serveur que vous quittez, réduisez le temps passé à attendre une réponse, car les problèmes réseau pourraient retarder l’arrêt de votre service.

Notez que pendant l’arrêt du service, par défaut, le SCM ne prend pas en compte les dépendances. Le SCM énumère les services en cours d’exécution et envoie la commande SERVICE_CONTROL_SHUTDOWN. Par conséquent, un service peut échouer, car un autre service dont il dépend est déjà arrêté.

Pour définir manuellement l’ordre d’arrêt des services, créez une valeur de Registre multistring qui contient les noms de service dans l’ordre dans lequel ils doivent être arrêtés et affectez-le à la valeur PreshutdownOrder de la clé de contrôle, comme suit :

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\PreshutdownOrder="Shutdown Order

Pour définir l’ordre d’arrêt des services dépendants de votre application, utilisez la fonction SetProcessShutdownParameters. Le gestionnaire SCM utilise cette fonction pour donner à son gestionnaire 0x1E0 priorité. Le SCM envoie SERVICE_CONTROL_SHUTDOWN notifications lorsque son gestionnaire de contrôle est appelé et attend que les services se terminent avant de revenir de son gestionnaire de contrôle.

écrire une fonction de gestionnaire de contrôles