Preciso escrever um código robusto no .NET para permitir que um serviço do Windows (servidor 2003) seja reiniciado. Qual é a melhor maneira de fazer isso? Existe alguma API .NET para fazer isso?
Preciso escrever um código robusto no .NET para permitir que um serviço do Windows (servidor 2003) seja reiniciado. Qual é a melhor maneira de fazer isso? Existe alguma API .NET para fazer isso?
Respostas:
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 - esqueço o nome dele). Então, sempre que desejar que o serviço reinicie, basta ligar Environment.Exit(1)
(ou qualquer retorno diferente de zero) e o sistema operacional o reiniciará para você.
Service.ExitCode = 1
e executar Service.Stop()
junto com a caixa de seleção 'Ativar ações para paradas com erros' na tela de configuração de recuperação de serviço. Fazer dessa maneira permite um desligamento adequado e ainda aciona a reinicialização.
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 permissões para parar e reiniciar o serviço.
Você pode criar um processo que é 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();
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 contabilizar espaços no nome do serviço, caso contrário, pode ser omitido).
Limpo, nenhuma configuração de reinicialização automática é necessária.
Depende do motivo pelo qual você deseja que ele seja reiniciado.
Se você está apenas procurando uma maneira de fazer com que o serviço se limpe periodicamente, poderá ter um timer em execução no serviço que periodicamente causa uma rotina de limpeza.
Se você estiver procurando uma maneira de reiniciar em caso de falha - o próprio host de serviço poderá fornecer essa capacidade quando estiver configurado.
Então, por que você precisa reiniciar o servidor? O que você está tentando alcançar?
Eu não acho que você possa em um serviço independente (quando você chamar Reiniciar, ele interromperá o serviço, o que interromperá o comando Reiniciar e nunca mais será iniciado). Se você puder adicionar um segundo .exe (um aplicativo de console que use a classe ServiceManager), poderá iniciar o .exe autônomo, reiniciar o serviço e sair.
Pensando bem, você provavelmente poderia fazer com que o serviço registrasse uma Tarefa Agendada (usando o comando 'at' da linha de comando, por exemplo) para iniciar o serviço e depois interromper a operação; isso provavelmente funcionaria.
O problema com a distribuição de um arquivo em lotes ou EXE é que um serviço pode ou não ter as permissões necessárias para executar o aplicativo externo.
A maneira mais limpa de fazer isso que encontrei é usar o método OnStop (), que é o ponto de entrada para o Service Control Manager. Todo o seu código de limpeza será executado e você não terá soquetes pendentes ou outros processos, supondo que seu código de parada esteja fazendo seu trabalho.
Para fazer isso, você precisa definir um sinalizador antes de terminar, que informa ao método OnStop para sair com um código de erro; o SCM sabe que o serviço precisa ser reiniciado. Sem esse sinalizador, você não poderá parar o serviço manualmente no SCM. Isso também pressupõe que você configurou o serviço para reiniciar com 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 reiniciar, inicio um encadeamento que interrompe o serviço do SCM. Isso permite que o serviço seja limpo depois de si mesmo:
...
if(NeedToRestart)
{
ABORT = true;
new Thread(RestartThread).Start();
}
void RestartThread()
{
ServiceController sc = new ServiceController(ServiceName);
try
{
sc.Stop();
}
catch (Exception) { }
}
Eu usaria o Windows Scheduler para agendar uma reinicialização do seu serviço. O problema é que você não pode se reiniciar, mas pode se parar. (Você essencialmente cortou o galho em que está sentado ... se você entender minha analogia) Você precisa de um processo separado para fazer isso por você. O Agendador do Windows é apropriado. Agende uma tarefa única para reiniciar o serviço (mesmo de dentro do próprio serviço) para executar imediatamente.
Caso contrário, você precisará criar um processo de "pastoreamento" que faça isso por você.
A primeira resposta à pergunta é a solução mais simples: "Environment.Exit (1)" Estou usando isso no Windows Server 2008 R2 e funciona perfeitamente. O serviço para automaticamente, o O / S aguarda 1 minuto e o reinicia.
A melhor abordagem pode ser utilizar o Serviço NT como um invólucro para seu aplicativo. Quando o serviço NT é iniciado, seu aplicativo pode iniciar no modo "ocioso" aguardando o início do comando (ou ser configurado para iniciar automaticamente).
Pense em um carro, quando é iniciado, ele começa em um estado ocioso, aguardando o comando avançar ou reverter. Isso também permite outros benefícios, como melhor administração remota, como você pode escolher como expor seu aplicativo.
Apenas de passagem: e pensei em adicionar algumas informações extras ...
você também pode lançar uma exceção, isso fechará automaticamente o serviço Windows e as opções de reinicialização automática serão ativadas. o único problema é que, se você tiver um ambiente de desenvolvimento no seu PC, o JIT tentará ativar, e você receberá uma mensagem dizendo debug Y / N. diga não e depois ele será fechado e reinicie corretamente. (em um PC sem JIT, tudo funciona). a razão pela qual estou trollando, esse JIT é novo no Win 7 (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, veja 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% iniciar
Crie um domínio de aplicativo separado para hospedar o código do aplicativo. Quando é necessário reiniciar, poderíamos descarregar e recarregar o domínio do aplicativo em vez do processo (serviço do Windows). É assim que o pool de aplicativos do IIS funciona, eles não executam o aplicativo asp.net diretamente, eles usam o domínio de aplicativo separado.
A maneira mais fácil é ter um arquivo em lotes com:
net stop net start
e adicione o arquivo ao planejador 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();
}
}