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




sc create service example parameters (15)

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?


Answer #1

O problema com descascar para 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 eu encontrei é usar o método OnStop (), que é o ponto de entrada para o Gerenciador de Controle de Serviços. 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 executando seu trabalho.

Para fazer isso, você precisa definir um sinalizador antes de finalizar que informe 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á parar 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) { }
}

Answer #2
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();
        }
    }

Answer #3
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()

Answer #4

Crie um appdomain separado para hospedar o código do aplicativo. Quando requer a reinicialização, 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 o appdmain separado.


Answer #5

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.


Answer #6

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

você também pode lançar uma exceção, isso irá automaticamente fechar o serviço do Windows, e as opções de reinício automático apenas entrarão. o único problema com isso é que se você tiver um ambiente de desenvolvimento em seu pc, o JIT tenta entrar em ação, e você receberá um prompt dizendo debug Y / N. diga não e, em seguida, ele será fechado e, em seguida, 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


Answer #7

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 estado ocioso, esperando que seu comando avance ou retroceda. Isso também permite outros benefícios, como melhor administração remota, pois você pode escolher como expor seu aplicativo.


Answer #8

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.


Answer #9

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();

Answer #10

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 classe ServiceManager), então você pode iniciar o .exe independente e fazer com que ele reinicie o serviço e 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, então, fazer com que ele parasse sozinho; isso provavelmente funcionaria.


Answer #11

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


Answer #12

Eu usaria o Agendador do Windows para agendar uma reinicialização do seu serviço. O problema é que você não pode se reiniciar, mas pode se impedir. (Você essencialmente arrancou o galho em que está sentada ... se tiver minha analogia) Você precisa de um processo separado para fazer isso por você. O Agendador do Windows é 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ê.


Answer #13

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ê poderia criar um processo desanexado para interromper o serviço, depois reiniciá-lo e depois sair.


Answer #14

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


Answer #15

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 o% service% for iniciado





windows-server-2003