Pregunta

Necesito escribir código robusto en .NET para permitir que un servicio de Windows (servidor 2003) se reinicie. ¿Cuál es la mejor manera de hacer esto? ¿Hay alguna API .NET para hacerlo?

¿Fue útil?

Solución

Configura el servicio para que se reinicie después de fallar (haz doble clic en el servicio en el panel de control y echa un vistazo a esas pestañas: olvido el nombre). Luego, cada vez que desee que se reinicie el servicio, simplemente llame a Environment.Exit (1) (o cualquier retorno que no sea cero) y el sistema operativo lo reiniciará por usted.

Otros consejos

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

No puede estar seguro de que la cuenta de usuario con la que se ejecuta su servicio tenga incluso permisos para detener y reiniciar el servicio.

Puede crear un proceso que es un símbolo del sistema de 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);

donde SERVICENAME es el nombre de su servicio (las comillas dobles incluidas para dar cuenta de los espacios en el nombre del servicio, pueden omitirse de otra forma).

Limpio, no es necesaria la configuración de reinicio automático.

Dependerá de por qué desea que se reinicie.

Si solo está buscando una manera de hacer que el servicio se limpie periódicamente, entonces podría tener un temporizador ejecutándose en el servicio que periódicamente causa una rutina de purga.

Si está buscando una forma de reiniciar en caso de falla, el host del servicio en sí puede proporcionar esa capacidad cuando se configura.

Entonces, ¿por qué necesita reiniciar el servidor? ¿Qué estás tratando de lograr?

No creo que pueda hacerlo en un servicio autónomo (cuando llama a Reiniciar, detendrá el servicio, lo que interrumpirá el comando Reiniciar, y nunca volverá a comenzar). Si puede agregar un segundo .exe (una aplicación de consola que usa la clase ServiceManager), puede iniciar el .exe independiente y hacer que reinicie el servicio y luego salga.

Pensándolo bien, es probable que el servicio registre una tarea programada (por ejemplo, mediante el comando 'at' de la línea de comandos) para iniciar el servicio y luego detenerlo; eso probablemente funcionaría.

El problema con la eliminación de un archivo por lotes o EXE es que un servicio puede o no tener los permisos necesarios para ejecutar la aplicación externa.

La forma más limpia de hacerlo que he encontrado es usar el método OnStop (), que es el punto de entrada para el Administrador de control de servicios. Entonces se ejecutará todo su código de limpieza, y no tendrá ningún zócalo colgante u otros procesos, asumiendo que su código de parada está haciendo su trabajo.

Para hacer esto, debe establecer una marca antes de terminar que le dice al método OnStop que salga con un código de error; entonces el SCM sabe que el servicio necesita reiniciarse. Sin este indicador, no podrá detener el servicio manualmente desde el SCM. Esto también asume que ha configurado el servicio para reiniciarse en un error.

Aquí está mi 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);
}

Si el servicio se ejecuta en un problema y necesita reiniciarse, inicio un subproceso que detiene el servicio desde el SCM. Esto permite que el servicio se limpie después de sí mismo:

...

if(NeedToRestart)
{
    ABORT = true;
    new Thread(RestartThread).Start();
}

void RestartThread()
{
    ServiceController sc = new ServiceController(ServiceName);
    try
    {
        sc.Stop();
    }
    catch (Exception) { }
}

Usaría el Programador de Windows para programar un reinicio de su servicio. El problema es que no puede reiniciarse, pero puede detenerse. (Esencialmente, usted ha recortado la rama en la que está sentado ... si obtiene mi analogía) Necesita un proceso separado para hacerlo por usted. El Programador de Windows es el adecuado. Programe una tarea única para reiniciar su servicio (incluso desde dentro del mismo servicio) para que se ejecute de inmediato.

De lo contrario, tendrá que crear un " pastoreo " proceso que lo hace por ti.

No creo que pueda. Cuando se detiene un servicio " " ;, se descarga totalmente.

Bueno, está bien, siempre hay una manera, supongo. Por ejemplo, podría crear un proceso separado para detener el servicio, luego reiniciarlo y luego salir.

La primera respuesta a la pregunta es la solución más simple: " Environment.Exit (1) " Estoy usando esto en Windows Server 2008 R2 y funciona perfectamente. El servicio se detiene solo, el O / S espera 1 minuto y luego lo reinicia.

Cree un dominio de aplicación separado para alojar el código de la aplicación. Cuando se requiere reiniciar, podríamos descargar y volver a cargar el dominio de aplicación en lugar del proceso (servicio de Windows). Así es como funciona el grupo de aplicaciones IIS, no ejecutan la aplicación asp.net directamente, usan appdmain por separado.

El mejor enfoque puede ser utilizar el Servicio NT como un contenedor para su aplicación. Cuando se inicia el servicio NT, su aplicación puede iniciarse en un " inactivo " Modo en espera de que se inicie el comando (o que se configure para iniciarse automáticamente).

Piense en un automóvil, cuando arranca, comienza en estado inactivo, esperando que su comando avance o retroceda. Esto también permite otros beneficios, como una mejor administración remota, ya que puede elegir cómo exponer su aplicación.

Simplemente pasando: y pensé que agregaría información adicional ...

también puede lanzar una excepción, esto cerrará automáticamente el servicio de Windows, y las opciones de reinicio automático simplemente se activan. El único problema con esto es que si tiene un entorno de desarrollo en su PC, entonces el JIT intenta patear, y obtendrás un mensaje que dice "depurar S / N". diga no y luego se cerrará, y luego se reiniciará correctamente. (En una PC sin JIT, todo funciona). La razón por la que estoy trolleando, es que este JIT es nuevo en Win 7 (solía funcionar bien con XP, etc.) y estoy tratando de encontrar una forma de deshabilitar el JIT ... Puedo probar el método Environment.Exit mencionado aquí, vea cómo eso también funciona.

Kristian: Bristol, Reino Unido

Crea un archivo 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%

Luego elimine la tarea% taskname% cuando comience su% service%

nssm es bastante bueno. Hará todo esto por ti

La forma más fácil es tener un archivo por lotes con:

parada neta inicio neto

y agregue el archivo al programador con el intervalo de tiempo que desee

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();
        }
    }
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top