Compartilhar via


Função ServiceMain

Quando um programa de controle de serviço solicita que um novo serviço seja executado, o SCM (Service Control Manager) inicia o serviço e envia uma solicitação inicial para o dispatcher de controle. O dispatcher de controle cria um novo thread para executar a funçãoServiceMain para o serviço. Para obter um exemplo, consulte Gravando uma função ServiceMain.

A funçãoServiceMain deve executar as seguintes tarefas:

  1. Inicializar todas as variáveis globais.

  2. Chame a funçãoRegisterServiceCtrlHandler imediatamente para registrar uma funçãodo Manipulador depara lidar com solicitações de controle para o serviço. O valor retornado de RegisterServiceCtrlHandler é um identificador de status de serviço que será usado em chamadas para notificar o SCM do status do serviço.

  3. Execute a inicialização. Se o tempo de execução do código de inicialização for muito curto (menos de um segundo), a inicialização poderá ser executada diretamente no ServiceMain.

    Se o tempo de inicialização for maior que um segundo, o serviço deverá usar uma das seguintes técnicas de inicialização:

    • Chame a função SetServiceStatus para relatar SERVICE_RUNNING mas não aceite controles até que a inicialização seja concluída. O serviço faz isso chamando SetServiceStatus com dwCurrentState definido como SERVICE_RUNNING e dwControlsAccepted definido como 0 na estrutura SERVICE_STATUS. Isso garante que o SCM não enviará nenhuma solicitação de controle para o serviço antes de estar pronto e libera o SCM para gerenciar outros serviços. Essa abordagem de inicialização é recomendada para o desempenho, especialmente para serviços de início automático.

    • Relatar SERVICE_START_PENDING, não aceitar controles e especificar uma dica de espera. Se o código de inicialização do serviço executar tarefas que devem levar mais tempo do que o valor da dica de espera inicial, seu código deverá chamar a função SetServiceStatus periodicamente (possivelmente com uma dica de espera revisada) para indicar que o progresso está sendo feito. Certifique-se de chamar SetServiceStatus somente se a inicialização estiver progredindo. Caso contrário, o SCM poderá aguardar a inserção do serviço no estado SERVICE_RUNNING supondo que seu serviço esteja progredindo e impedir que outros serviços sejam iniciados. Não chame SetServiceStatus de um thread separado, a menos que você tenha certeza de que o thread que está executando a inicialização está realmente fazendo progresso.

      Um serviço que usa essa abordagem também pode especificar um valor de ponto de verificação e incrementar o valor periodicamente durante uma inicialização demorada. O programa que iniciou o serviço pode chamar queryServiceStatus ou QueryServiceStatusEx para obter o valor de ponto de verificação mais recente do SCM e usar o valor para relatar o progresso incremental para o usuário.

  4. Quando a inicialização for concluída, chame SetServiceStatus para definir o estado do serviço como SERVICE_RUNNING e especificar os controles que o serviço está preparado para aceitar. Para obter uma lista de controles, consulte a estrutura SERVICE_STATUS.

  5. Execute as tarefas de serviço ou, se não houver tarefas pendentes, retorne o controle ao chamador. Qualquer alteração no estado de serviço garante uma chamada para SetServiceStatus para relatar novas informações de status.

  6. Se ocorrer um erro enquanto o serviço estiver inicializando ou em execução, o serviço deverá chamar SetServiceStatus para definir o estado do serviço como SERVICE_STOP_PENDING se a limpeza for longa. Após a conclusão da limpeza, chame SetServiceStatus para definir o estado do serviço como SERVICE_STOPPED do último thread a ser encerrado. Certifique-se de definir os dwServiceSpecificExitCode e dwWin32ExitCode membros da estrutura SERVICE_STATUS para identificar o erro.

escrever uma função ServiceMain