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:
Inicializar todas as variáveis globais.
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.
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.
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.
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.
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.
Tópicos relacionados