Service ServiceMain (Función)

Cuando un programa de control de servicio solicita que se ejecute un nuevo servicio, Service Control Manager (SCM) inicia el servicio y envía una solicitud de inicio al distribuidor de control. El distribuidor de controles crea un subproceso para ejecutar la función ServiceMain para el servicio. Para obtener un ejemplo, consulte Escritura de una función ServiceMain.

La función ServiceMain debe realizar las siguientes tareas:

  1. Inicialice todas las variables globales.

  2. Llame a la función RegisterServiceCtrlHandler inmediatamente para registrar una función handler para controlar las solicitudes de control del servicio. El valor devuelto de RegisterServiceCtrlHandler es un identificador de estado de servicio que se usará en las llamadas para notificar al SCM del estado del servicio.

  3. Realice la inicialización. Si se espera que el tiempo de ejecución del código de inicialización sea muy corto (menos de un segundo), la inicialización se puede realizar directamente en ServiceMain.

    Si se espera que el tiempo de inicialización sea superior a un segundo, el servicio debe usar una de las siguientes técnicas de inicialización:

    • Llame a la función SetServiceStatus para notificar SERVICE_RUNNING pero no acepte controles hasta que finalice la inicialización. El servicio lo hace llamando a SetServiceStatus con dwCurrentState establecido en SERVICE_RUNNING y dwControlsAccepted establecido en 0 en la estructura SERVICE_STATUS . Esto garantiza que el SCM no enviará ninguna solicitud de control al servicio antes de que esté lista y libere el SCM para administrar otros servicios. Este enfoque para la inicialización se recomienda para el rendimiento, especialmente para los servicios de inicio automático.

    • Informe SERVICE_START_PENDING, no acepte controles y especifique una sugerencia de espera. Si el código de inicialización del servicio realiza tareas que se espera que tarden más tiempo que el valor de la sugerencia de espera inicial, el código debe llamar periódicamente a la función SetServiceStatus (posiblemente con una sugerencia de espera revisada) para indicar que se está realizando el progreso. Asegúrese de llamar a SetServiceStatus solo si la inicialización está progresando. De lo contrario, el SCM puede esperar a que el servicio entre en el estado SERVICE_RUNNING suponiendo que el servicio está progresando y que impide que se inicien otros servicios. No llame a SetServiceStatus desde un subproceso independiente a menos que esté seguro de que el subproceso que realiza la inicialización está progresando realmente.

      Un servicio que usa este enfoque también puede especificar un valor de punto de comprobación e incrementar el valor periódicamente durante una inicialización larga. El programa que inició el servicio puede llamar a QueryServiceStatus o QueryServiceStatusEx para obtener el valor de punto de comprobación más reciente del SCM y usar el valor para notificar el progreso incremental al usuario.

  4. Cuando se complete la inicialización, llame a SetServiceStatus para establecer el estado del servicio en SERVICE_RUNNING y especifique los controles que el servicio está preparado para aceptar. Para obtener una lista de controles, vea la estructura SERVICE_STATUS .

  5. Realice las tareas del servicio o, si no hay ninguna tarea pendiente, devuelva el control al autor de la llamada. Cualquier cambio en el estado del servicio garantiza una llamada a SetServiceStatus para notificar la nueva información de estado.

  6. Si se produce un error mientras el servicio se está inicializando o ejecutando, el servicio debe llamar a SetServiceStatus para establecer el estado del servicio en SERVICE_STOP_PENDING si la limpieza será larga. Una vez completada la limpieza, llame a SetServiceStatus para establecer el estado del servicio en SERVICE_STOPPED desde el último subproceso para finalizar. Asegúrese de establecer los miembros dwServiceSpecificExitCode y dwWin32ExitCode de la estructura SERVICE_STATUS para identificar el error.

Escritura de una función ServiceMain