Compartir a través de


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 nuevo subproceso para ejecutar la función ServiceMain para el servicio. Para obtener un ejemplo, consulte Escritura de una función ServiceMain.

La funciónserviceMain dedebe realizar las siguientes tareas:

  1. Inicialice todas las variables globales.

  2. Llame a la funciónRegisterServiceCtrlHandler inmediatamente para registrar una funcióncontrolador depara controlar las solicitudes de control del servicio. El valor devuelto de RegisterServiceCtrlHandler es un identificador de estado del servicio que se usará en 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ónSetServiceStatus para notificar SERVICE_RUNNING, pero no acepte ningún control 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 de 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, acepte ningún control 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 sugerencia de espera inicial, el código debe llamar a la función SetServiceStatus periódicamente (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 bloquee el inicio de 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 último valor de punto de comprobación del SCM y usar el valor para notificar el progreso incremental al usuario.

  4. Una vez completada 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, consulte la estructura SERVICE_STATUS.

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

  6. Si se produce un error al inicializar o ejecutar el servicio, 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 el dwServiceSpecificExitCode de y dwWin32ExitCode miembros de la estructura de SERVICE_STATUS para identificar el error.

escribir una función ServiceMain