Como um serviço do Windows pode se reiniciar programaticamente?

Eu preciso escrever um código robusto no .NET para permitir que um serviço do Windows (servidor 2003) reinicie a si mesmo. Qual é o melhor caminho para isso? Existe alguma API .NET para fazer isso?

   

Defina o serviço para reiniciar após falha (clique duas vezes no serviço no painel de controle e dê uma olhada nessas guias – esqueci o nome dele). Então, sempre que você quiser que o serviço seja reiniciado, basta chamar Environment.Exit(1) (ou qualquer retorno diferente de zero) e o sistema operacional irá reiniciá-lo para você.

 Dim proc As New Process() Dim psi As New ProcessStartInfo() psi.CreateNoWindow = True psi.FileName = "cmd.exe" psi.Arguments = "/C net stop YOURSERVICENAMEHERE && net start YOURSERVICENAMEHERE" psi.LoadUserProfile = False psi.UseShellExecute = False psi.WindowStyle = ProcessWindowStyle.Hidden proc.StartInfo = psi proc.Start() 

Você não pode ter certeza de que a conta de usuário em que seu serviço está sendo executado tem permissions para parar e reiniciar o serviço.

 const string strCmdText = "/C net stop \"SERVICENAME\"&net start \"SERVICENAME\""; Process.Start("CMD.exe", strCmdText); 

onde SERVICENAME é o nome do seu serviço (aspas duplas incluídas para considerar os espaços no nome do serviço, podem ser omitidas de outra forma).

Limpo, nenhuma configuração de reboot automática é necessária.

Você pode criar um processo que seja um prompt de comando do DOS que se reinicia:

  Process process = new Process(); process.StartInfo.FileName = "cmd"; process.StartInfo.Arguments = "/c net stop \"servicename\" & net start \"servicename\""; process.Start(); 

Isso dependeria do motivo pelo qual você deseja que ele seja reiniciado.

Se você está apenas procurando uma maneira de ter o serviço limpo periodicamente, então você pode ter um timer em execução no serviço que periodicamente provoca uma rotina de limpeza.

Se você estiver procurando uma maneira de reiniciar em caso de falha – o próprio host de serviço pode fornecer essa capacidade quando for configurado.

Então, por que você precisa reiniciar o servidor? O que você está tentando alcançar?

Eu não acho que você pode em um serviço auto-contido (quando você chama Restart, ele irá parar o serviço, o que irá interromper o comando Restart, e ele nunca vai começar de novo). Se você pode adicionar um segundo .exe (um aplicativo de console que usa a class ServiceManager), então você pode iniciar o .exe independente e fazer com que ele reinicie o serviço e, em seguida, saia.

Pensando bem, você poderia provavelmente ter o serviço registrando uma Tarefa Agendada (usando o comando ‘at’ da linha de comando, por exemplo) para iniciar o serviço e depois parar; isso provavelmente funcionaria.

Eu usaria o Agendador do Windows para agendar uma reboot do seu serviço. O problema é que você não pode se reiniciar, mas pode se impedir. (Você essencialmente cortou o ramo em que está sentada … se tiver minha analogia) Você precisa de um processo separado para fazer isso por você. O Windows Scheduler é apropriado. Programe uma tarefa única para reiniciar o serviço (mesmo a partir do próprio serviço) para executar imediatamente.

Caso contrário, você terá que criar um processo de “pastoreio” que faça isso para você.

O problema com descascar para um arquivo em lotes ou EXE é que um serviço pode ou não ter as permissions necessárias para executar o aplicativo externo.

A maneira mais limpa de fazer isso é usar o método OnStop (), que é o ponto de input do Gerenciador de Controle de Serviço. Em seguida, todo o seu código de limpeza será executado e você não terá nenhum soquete suspenso ou outros processos, supondo que seu código de parada esteja fazendo seu trabalho.

Para fazer isso, você precisa definir um sinalizador antes de finalizar, informando ao método OnStop para sair com um código de erro; então o SCM sabe que o serviço precisa ser reiniciado. Sem esse sinalizador, você não poderá interromper o serviço manualmente no SCM. Isso também pressupõe que você tenha configurado o serviço para reiniciar em um erro.

Aqui está o meu código de parada:

 ... bool ABORT; protected override void OnStop() { Logger.log("Stopping service"); WorkThreadRun = false; WorkThread.Join(); Logger.stop(); // if there was a problem, set an exit error code // so the service manager will restart this if(ABORT)Environment.Exit(1); } 

Se o serviço tiver um problema e precisar ser reiniciado, inicio um encadeamento que interrompe o serviço do SCM. Isso permite que o serviço se limpe depois de si:

 ... if(NeedToRestart) { ABORT = true; new Thread(RestartThread).Start(); } void RestartThread() { ServiceController sc = new ServiceController(ServiceName); try { sc.Stop(); } catch (Exception) { } } 

Eu não acho que pode. Quando um serviço é “interrompido”, ele é totalmente descarregado.

Bem, ok, sempre há uma maneira que eu suponho. Por exemplo, você pode criar um processo desanexado para interromper o serviço, depois reiniciá-lo e sair.

A primeira resposta para a pergunta é a solução mais simples: “Environment.Exit (1)” Estou usando isso no Windows Server 2008 R2 e funciona perfeitamente. O serviço pára, o O / S aguarda 1 minuto e reinicia.

Crie um appdomain separado para hospedar o código do aplicativo. Quando requer a reboot, podemos descarregar e recarregar o appdomain em vez do processo (serviço do windows). É assim que funciona o pool de aplicativos do IIS, eles não executam o aplicativo asp.net diretamente, eles usam appdmain separados.

A melhor abordagem pode ser utilizar o Serviço NT como um wrapper para seu aplicativo. Quando o Serviço NT é iniciado, seu aplicativo pode iniciar em um modo “inativo” aguardando o início do comando (ou ser configurado para iniciar automaticamente).

Pense em um carro, quando ele é iniciado, ele começa em um estado ocioso, esperando que seu comando avance ou retroceda. Isso também permite outros benefícios, como uma melhor administração remota, pois você pode escolher como expor seu aplicativo.

Apenas passando: e pensei que gostaria de acrescentar alguma informação extra …

você também pode lançar uma exceção, isso fechará automaticamente o serviço do Windows, e as opções de reboot automática apenas serão acionadas. O único problema com isso é que, se você tiver um ambiente de desenvolvimento em seu computador, o JIT tentará entrar em ação. e você receberá um prompt dizendo debug Y / N. diga não e então feche, e então reinicie corretamente. (em um PC sem JIT, tudo funciona). a razão pela qual eu estou trolling, é este JIT é novo para Win 7 (ele costumava funcionar bem com o XP etc) e estou tentando encontrar uma maneira de desabilitar o JIT …. eu posso tentar o método Environment.Exit mencionado aqui ver como isso funciona também.

Kristian: Bristol, Reino Unido

Crie um arquivo restart.bat como este

 @echo on set once="C:\Program Files\MyService\once.bat" set taskname=Restart_MyService set service=MyService echo rem %time% >%once% echo net stop %service% >>%once% echo net start %service% >>%once% echo del %once% >>%once% schtasks /create /ru "System" /tn %taskname% /tr '%once%' /sc onstart /F /V1 /Z schtasks /run /tn %taskname% 

Em seguida, exclua a tarefa% taskname% quando seu% service% for iniciado

O nssm é muito bom. fará tudo isso por você

A maneira mais fácil é ter um arquivo em lotes com:

net stop net start

e adicione o arquivo ao agendador com o intervalo de tempo desejado

 private static void RestartService(string serviceName) { using (var controller = new ServiceController(serviceName)) { controller.Stop(); int counter = 0; while (controller.Status != ServiceControllerStatus.Stopped) { Thread.Sleep(100); controller.Refresh(); counter++; if (counter > 1000) { throw new System.TimeoutException(string.Format("Could not stop service: {0}", Constants.Series6Service.WindowsServiceName)); } } controller.Start(); } }