Função do manipulador do controle de serviço
Cada serviço tem um manipulador de controle, a função Handler , que é invocado pelo dispatcher de controle quando o processo de serviço recebe uma solicitação de controle de um programa de controle de serviço. Portanto, essa função é executada no contexto do dispatcher de controle. Para obter um exemplo, consulte Escrevendo uma função de manipulador de controle.
Um serviço chama a função RegisterServiceCtrlHandler ou RegisterServiceCtrlHandlerEx para registrar sua função de manipulador de controle de serviço.
Quando o manipulador de controle de serviço é invocado, o serviço deve chamar a função SetServiceStatus para relatar sua status ao SCM somente se o tratamento do código de controle fizer com que o serviço status seja alterado. Se o tratamento do código de controle não fizer com que o serviço status seja alterado, não será necessário chamar SetServiceStatus.
Um programa de controle de serviço pode enviar solicitações de controle usando a função ControlService . Todos os serviços devem aceitar e processar o código de controle SERVICE_CONTROL_INTERROGATE . Você pode habilitar ou desabilitar a aceitação dos outros códigos de controle chamando SetServiceStatus. Para receber o código de controle SERVICE_CONTROL_DEVICEEVENT , você deve chamar a função RegisterDeviceNotification . Os serviços também podem lidar com códigos de controle adicionais definidos pelo usuário.
Se um serviço aceitar o código de controle SERVICE_CONTROL_STOP , ele deverá parar após o recebimento, indo para o estado SERVICE_STOP_PENDING ou SERVICE_STOPPED . Depois que o SCM enviar esse código de controle, ele não enviará outros códigos de controle.
Windows XP: Se o serviço retornar NO_ERROR e continuar a ser executado, ele continuará recebendo códigos de controle. Esse comportamento mudou a partir do Windows Server 2003 e do Windows XP com Service Pack 2 (SP2).
O manipulador de controle deve retornar dentro de 30 segundos ou o SCM retorna um erro. Se um serviço precisar fazer processamento longo quando o serviço estiver executando o manipulador de controle, ele deverá criar um thread secundário para executar o processamento longo e, em seguida, retornar do manipulador de controle. Isso impede que o serviço acione o dispatcher de controle. Por exemplo, ao lidar com a solicitação de parada para um serviço que leva muito tempo, crie outro thread para lidar com o processo de parada. O manipulador de controle deve simplesmente chamar SetServiceStatus com a mensagem SERVICE_STOP_PENDING e retornar.
Quando o usuário desliga o sistema, todos os manipuladores de controle que chamaram SetServiceStatus com o código de controle SERVICE_ACCEPT_PRESHUTDOWN recebem o código de controle SERVICE_CONTROL_PRESHUTDOWN . O gerenciador de controle de serviço aguarda até que o serviço pare ou o valor de tempo limite de pré-desligamento especificado expire (esse valor pode ser definido com a função ChangeServiceConfig2 ). Esse código de controle deve ser usado apenas em circunstâncias especiais, pois um serviço que manipula essa notificação bloqueia o desligamento do sistema até que o serviço pare ou o intervalo de tempo limite de pré-desligamento expire.
Depois que as notificações de pré-desligamento forem concluídas, todos os manipuladores de controle que chamaram SetServiceStatus com o código de controle SERVICE_ACCEPT_SHUTDOWN receberão o código de controle SERVICE_CONTROL_SHUTDOWN . Eles são notificados na ordem em que aparecem no banco de dados de serviços instalados. Por padrão, um serviço tem aproximadamente 20 segundos para executar tarefas de limpeza antes que o sistema seja desligado. Depois que esse tempo expirar, o desligamento do sistema continuará independentemente de o desligamento do serviço ser concluído. Observe que, se o sistema for deixado no estado de desligamento (não reiniciado ou desligado), o serviço continuará sendo executado.
Se o serviço exigir mais tempo para limpeza, ele enviará STOP_PENDING status mensagens, juntamente com uma dica de espera, para que o controlador de serviço saiba quanto tempo aguardar antes de relatar ao sistema que o desligamento do serviço foi concluído. No entanto, para impedir que um serviço pare o desligamento, há um limite para quanto tempo o controlador de serviço aguarda. Se o serviço estiver sendo desligado por meio do snap-in Serviços, o limite será de 125 segundos ou 125.000 milissegundos. Se o sistema operacional estiver sendo reinicializado, o limite de tempo será especificado no valor WaitToKillServiceTimeout (em milissegundos) da seguinte chave do Registro:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control
Importante
Um serviço não deve tentar aumentar o limite de tempo modificando esse valor. Se você precisar definir WaitToKillServiceTimeout manualmente, o valor deverá estar em milissegundos.
Os clientes exigem desligamento rápido do sistema operacional. Por exemplo, se um computador em execução na energia ups não puder concluir o desligamento antes que o UPS fique sem energia, os dados poderão ser perdidos. Portanto, os serviços devem concluir suas tarefas de limpeza o mais rápido possível. É uma boa prática minimizar dados não salvos salvando dados regularmente, acompanhando os dados salvos no disco e salvando apenas os dados não salvos no desligamento. Como o computador está sendo desligado, não gaste tempo liberando memória alocada ou outros recursos do sistema. Se você precisar notificar um servidor de que está saindo, minimize o tempo gasto aguardando uma resposta, pois problemas de rede podem atrasar o desligamento do serviço.
Observe que, durante o desligamento do serviço, por padrão, o SCM não leva em consideração as dependências. O SCM enumera a lista de serviços em execução e envia o comando SERVICE_CONTROL_SHUTDOWN . Portanto, um serviço pode falhar porque outro serviço do qual ele depende já foi interrompido.
Para definir a ordem de desligamento dos serviços manualmente, crie um valor de registro de várias cadeias de caracteres que contém os nomes de serviço na ordem em que eles devem ser desligados e atribua-o ao valor PreshutdownOrder da chave de controle, da seguinte maneira:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\PreshutdownOrder="Shutdown Order"
Para definir a ordem de desligamento dos serviços dependentes do aplicativo, use a função SetProcessShutdownParameters . O SCM usa essa função para dar ao manipulador 0x1E0 prioridade. O SCM envia SERVICE_CONTROL_SHUTDOWN notificações quando seu manipulador de controle é chamado e aguarda a saída dos serviços antes de retornar de seu manipulador de controle.
Tópicos relacionados