Share via


Fonction du gestionnaire de contrôle des services

Chaque service a un gestionnaire de contrôles, la fonction Handler , qui est appelé 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ôle.

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 ses status au SCM uniquement si la gestion du code de contrôle entraîne la modification du service status. Si la gestion du code de contrôle n’entraîne pas de modification du status de 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 fonction ControlService . 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 supplémentaires définis par l’utilisateur.

Si un service accepte le code de contrôle SERVICE_CONTROL_STOP , il doit s’arrêter à la réception, en accédant à l’état SERVICE_STOP_PENDING ou SERVICE_STOPPED . Une fois que le SCM a envoyé 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 de s’exécuter, il continue de recevoir des codes de contrôle. Ce comportement a changé à partir de Windows Server 2003 et de Windows XP avec Service Pack 2 (SP2).

Le gestionnaire de contrôles doit retourner dans un délai de 30 secondes, ou le SCM 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 revenir à partir du gestionnaire de contrôle. Cela empêche le service de lier le répartiteur de contrôle. Par exemple, lors de la gestion de la demande d’arrêt pour un service qui prend beaucoup de temps, créez un autre thread pour gérer le processus d’arrêt. Le gestionnaire de contrôles 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’expiration 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 cette notification bloque l’arrêt du système jusqu’à ce que le service s’arrête ou que l’intervalle de délai d’attente de pré-arrêt expire.

Une fois les notifications de pré-arrêt terminées, tous les gestionnaires de contrôles 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 dispose d’environ 20 secondes pour effectuer des tâches de nettoyage avant l’arrêt du système. Une fois ce délai expiré, l’arrêt du système se poursuit, que l’arrêt du service soit terminé ou non. Notez que si le système est laissé à l’état d’arrêt (pas redémarré ou hors tension), le service continue de s’exécuter.

Si le service a besoin de plus de temps pour le nettoyage, il envoie STOP_PENDING messages status, 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 d’attente du contrôleur de service. Si le service est arrêté via le composant logiciel enfichable Services, la limite est de 125 secondes, soit 125 000 millisecondes. Si le système d’exploitation redémarre, la limite de temps est spécifiée dans la valeur WaitToKillServiceTimeout (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 à la main, la valeur doit être en millisecondes.

Les clients nécessitent un arrêt rapide du système d’exploitation. Par exemple, si un ordinateur s’exécutant sur l’ondeur ne peut pas s’arrêter avant que l’UPS ne soit à court d’alimentation, des données peuvent être perdues. Par conséquent, les services doivent effectuer leurs tâches de nettoyage aussi rapidement que possible. Il est recommandé de réduire au minimum les données non enregistrées en enregistrant régulièrement les données, en effectuant le suivi des données enregistrées sur le disque et en enregistrant uniquement vos données non enregistrées lors de l’arrêt. Étant donné que l’ordinateur est en cours d’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 d’attente d’une réponse, car les problèmes réseau peuvent 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 la liste des 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 s’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 SCM utilise cette fonction pour accorder à 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 quittent avant de revenir de son gestionnaire de contrôle.

Écriture d’une fonction de gestionnaire de contrôles