Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
Quando um programa de controle de serviço solicita que um novo serviço seja executado, o Gerenciador de Controle de Serviço (SCM) inicia o serviço e envia uma solicitação de início para o dispatcher de controle. O dispatcher de controle cria um novo thread para executar a função ServiceMain para o serviço. Para obter um exemplo, consulte Escrevendo uma função ServiceMain.
A função ServiceMain deve executar as seguintes tarefas:
Inicialize todas as variáveis globais.
Chame a funçãoRegisterServiceCtrlHandler imediatamente para registrar uma funçãoHandlerpara lidar com solicitações de controle para o serviço. O valor de retorno 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 se espera que o tempo de execução do código de inicialização seja muito curto (menos de um segundo), a inicialização pode ser executada diretamente no ServiceMain.
Se se espera que o tempo de inicialização seja superior a um segundo, o serviço deve usar uma das seguintes técnicas de inicialização:
Chame a função SetServiceStatus para relatar SERVICE_RUNNING mas não aceite nenhum controle 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 que ele esteja pronto e libera o SCM para gerenciar outros serviços. Essa abordagem de inicialização é recomendada para desempenho, especialmente para serviços de inicialização automática.
Relatório SERVICE_START_PENDING, não aceite nenhum controle e especifique 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 inicial da dica de espera, o 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 pode aguardar que o serviço entre no estado SERVICE_RUNNING, supondo que o serviço esteja progredindo e bloqueando a inicialização de outros serviços. Não chame SetServiceStatus de um thread separado, a menos que tenha certeza de que o thread que executa a inicialização está realmente progredindo.
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 estiver concluída, chame SetServiceStatus para definir o estado do serviço como SERVICE_RUNNING e especifique 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 para o chamador. Qualquer alteração no estado do serviço justifica uma chamada para SetServiceStatus para relatar novas informações de status.
Se ocorrer um erro durante a inicialização ou execução do serviço, o serviço deverá chamar SetServiceStatus para definir o estado do serviço como SERVICE_STOP_PENDING se a limpeza for demorada. Após a conclusão da limpeza, chame SetServiceStatus para definir o estado do serviço para SERVICE_STOPPED do último thread a ser encerrado. Certifique-se de definir o dwServiceSpecificExitCode e dwWin32ExitCode membros da estrutura SERVICE_STATUS para identificar o erro.
Tópicos relacionados