Función de controlador de control de servicio

Cada servicio tiene un controlador de control, la función Handler , invocada por el distribuidor de controles cuando el proceso de servicio recibe una solicitud de control de un programa de control de servicio. Por lo tanto, esta función se ejecuta en el contexto del distribuidor de control. Para obtener un ejemplo, vea Escribir una función de controlador de control.

Un servicio llama a la función RegisterServiceCtrlHandler o RegisterServiceCtrlHandlerEx para registrar su función de controlador de control de servicio.

Cuando se invoca el controlador de control de servicio, el servicio debe llamar a la función SetServiceStatus para notificar su estado al SCM solo si controlar el código de control hace que el estado del servicio cambie. Si el control del código de control no hace que el estado del servicio cambie, no es necesario llamar a SetServiceStatus.

Un programa de control de servicio puede enviar solicitudes de control mediante la función ControlService . Todos los servicios deben aceptar y procesar el código de control SERVICE_CONTROL_INTERROGATE . Puede habilitar o deshabilitar la aceptación de los otros códigos de control llamando a SetServiceStatus. Para recibir el código de control SERVICE_CONTROL_DEVICEEVENT , debe llamar a la función RegisterDeviceNotification . Los servicios también pueden controlar códigos de control adicionales definidos por el usuario.

Si un servicio acepta el código de control de SERVICE_CONTROL_STOP , debe detenerse al recibirlo, yendo al estado SERVICE_STOP_PENDING o SERVICE_STOPPED . Una vez que el SCM envía este código de control, no enviará otros códigos de control.

Windows XP: Si el servicio devuelve NO_ERROR y continúa ejecutándose, continúa recibiendo códigos de control. Este comportamiento cambió a partir de Windows Server 2003 y Windows XP con Service Pack 2 (SP2).

El controlador de control debe devolver en un plazo de 30 segundos o el SCM devuelve un error. Si un servicio debe realizar un procesamiento prolongado cuando el servicio ejecuta el controlador de control, debe crear un subproceso secundario para realizar el procesamiento largo y, a continuación, volver del controlador de control. Esto evita que el servicio se ata al distribuidor de controles. Por ejemplo, al controlar la solicitud de detención de un servicio que tarda mucho tiempo, cree otro subproceso para controlar el proceso de detención. El controlador de control simplemente debe llamar a SetServiceStatus con el mensaje SERVICE_STOP_PENDING y devolver.

Cuando el usuario cierra el sistema, todos los controladores de control que han llamado a SetServiceStatus con el código de control SERVICE_ACCEPT_PRESHUTDOWN reciben el código de control SERVICE_CONTROL_PRESHUTDOWN . El administrador de control de servicio espera hasta que el servicio se detenga o expire el valor de tiempo de espera de preshutdown especificado (este valor se puede establecer con la función ChangeServiceConfig2 ). Este código de control solo se debe usar en circunstancias especiales, ya que un servicio que controla esta notificación bloquea el apagado del sistema hasta que el servicio se detiene o expira el intervalo de tiempo de espera previo.

Una vez completadas las notificaciones previas, todos los controladores de control que han llamado a SetServiceStatus con el código de control SERVICE_ACCEPT_SHUTDOWN reciben el código de control de SERVICE_CONTROL_SHUTDOWN . Se les notifica en el orden en que aparecen en la base de datos de los servicios instalados. De forma predeterminada, un servicio tiene aproximadamente 20 segundos para realizar tareas de limpieza antes de que se cierre el sistema. Después de que expire este tiempo, el apagado del sistema continúa independientemente de si se ha completado el apagado del servicio. Tenga en cuenta que si el sistema se deja en estado de apagado (no reiniciado o apagado), el servicio continúa ejecutándose.

Si el servicio requiere más tiempo para limpiarlo, envía STOP_PENDING mensajes de estado, junto con una sugerencia de espera, por lo que el controlador de servicio sabe cuánto tiempo esperar antes de notificar al sistema que se completa el apagado del servicio. Sin embargo, para evitar que un servicio detenga el apagado, hay un límite durante cuánto tiempo espera el controlador de servicio. Si el servicio se está cerrando a través del complemento Servicios, el límite es de 125 segundos o 125 000 milisegundos. Si el sistema operativo se está reiniciando, el límite de tiempo se especifica en el valor WaitToKillServiceTimeout (en milisegundos) de la siguiente clave del Registro:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control

Importante

Un servicio no debe intentar aumentar el límite de tiempo modificando este valor. Si necesita establecer WaitToKillServiceTimeout a mano, el valor debe estar en milisegundos.

Los clientes requieren un apagado rápido del sistema operativo. Por ejemplo, si un equipo que se ejecuta en la alimentación UPS no puede completar el apagado antes de que el UPS se quede sin energía, se pueden perder datos. Por lo tanto, los servicios deben completar sus tareas de limpieza lo antes posible. Se recomienda minimizar los datos no guardados guardando datos periódicamente, realizando un seguimiento de los datos guardados en el disco y guardando solo los datos no guardados durante el apagado. Dado que el equipo se está apagando, no dedique tiempo a liberar memoria asignada u otros recursos del sistema. Si necesita notificar a un servidor que sale, minimice el tiempo dedicado a esperar una respuesta, ya que los problemas de red podrían retrasar el apagado del servicio.

Tenga en cuenta que, durante el apagado del servicio, de forma predeterminada, el SCM no tiene en cuenta las dependencias. El SCM enumera la lista de servicios en ejecución y envía el comando SERVICE_CONTROL_SHUTDOWN . Por lo tanto, un servicio puede producir un error porque otro servicio depende de que ya se ha detenido.

Para establecer manualmente el orden de apagado de los servicios, cree un valor del Registro de varias cadena que contenga los nombres de servicio en el orden en el que se deben apagar y asígnelo al valor PreshutdownOrder de la clave de control, como se indica a continuación:

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

Para establecer el orden de apagado de los servicios dependientes de la aplicación, use la función SetProcessShutdownParameters . El SCM usa esta función para conceder a su controlador 0x1E0 prioridad. El SCM envía SERVICE_CONTROL_SHUTDOWN notificaciones cuando se llama a su controlador de control y espera a que los servicios salgan antes de volver de su controlador de control.

Escritura de una función de controlador de control