¿Cómo puede un servicio de Windows reiniciarse programáticamente?

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

Configure el servicio para que se reinicie después de la falla (haga doble clic en el servicio en el panel de control y eche un vistazo a esas tabs; se me olvida el nombre). Luego, cada vez que desee que el servicio se reinicie, simplemente llame a Environment.Exit(1) (o cualquier devolución distinta de cero) y el sistema operativo lo reiniciará por usted.

 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 bajo la que se ejecuta su servicio tenga permisos para detener y reiniciar el servicio.

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

donde SERVICENAME es el nombre de su servicio (se pueden omitir las comillas dobles incluidas para contabilizar espacios en el nombre del servicio).

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

Puede crear un proceso que sea un símbolo del sistema de DOS que se reinicie usted mismo:

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

Dependerá de por qué quieres que se reinicie solo.

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

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

Entonces, ¿por qué necesitas reiniciar el servidor? ¿Qué estás intentando lograr?

No creo que pueda hacerlo en un servicio autónomo (cuando llame a Restart, detendrá el servicio, lo que interrumpirá el comando Restart y no volverá a iniciarse). Si puede agregar un segundo .exe (una aplicación de consola que utiliza la clase ServiceManager), puede iniciar el .exe independiente y hacer que reinicie el servicio y luego salir.

Pensándolo bien, probablemente puedas hacer que el servicio registre una tarea progtwigda (usando el comando de línea de comando ‘at’, por ejemplo) para iniciar el servicio y luego hacer que se detenga; eso probablemente funcionaría.

Usaría el Progtwigdor de Windows para progtwigr un reinicio de su servicio. El problema es que no puedes reiniciar tú mismo, pero puedes detenerte a ti mismo. (En esencia, cortaste la twig en la que estás sentado … si entiendes mi analogía). Necesitas un proceso separado para hacerlo por ti. El Progtwigdor de Windows es apropiado. Programe una tarea única para reiniciar su servicio (incluso desde el propio servicio) para ejecutarlo de inmediato.

De lo contrario, tendrás que crear un proceso de “pastoreo” que lo haga por ti.

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

La forma más limpia de hacer esto que he encontrado es usar el método OnStop (), que es el punto de entrada para el Administrador de control de servicios. Luego se ejecutará todo su código de limpieza, y no tendrá ningún sockets colgantes u otros procesos, suponiendo que su código de detención está haciendo su trabajo.

Para hacer esto, necesita establecer un indicador antes de terminar que le indique al método OnStop que salga con un código de error; entonces, el SCM sabe que el servicio debe reiniciarse. Sin este indicador, no podrá detener el servicio manualmente desde el SCM. Esto también asume que ha configurado el servicio para reiniciar en caso de 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 encuentra con un problema y necesita reiniciarse, ejecuto un hilo que detiene el servicio desde el SCM. Esto permite que el servicio 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) { } } 

No creo que pueda Cuando un servicio se “detiene”, se descarga por completo.

Bueno, está bien, siempre hay una manera que supongo. Por ejemplo, puede 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 sea necesario reiniciar, podríamos descargar y volver a cargar el dominio de la aplicación en lugar del proceso (servicio de Windows). Así es como funciona el grupo de aplicaciones de IIS, no ejecutan la aplicación asp.net directamente, sino que 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 modo “inactivo” esperando a que comience el comando (o se configure para que se inicie automáticamente).

Piense en un automóvil, cuando se inicia 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.

De paso: y pensé en agregar algo de información extra …

también puedes lanzar una excepción, esto cerrará automáticamente el servicio de Windows, y las opciones de reinicio automático solo entrarán en juego. El único problema con esto es que si tienes un entorno de desarrollo en tu PC, entonces el JIT intenta entrar en acción, y obtendrá un mensaje que dice depurar S / N. di no y luego se cerrará y luego volverá a comenzar correctamente. (en una PC sin JIT todo funciona). la razón por la que estoy trolling, es que este JIT es nuevo para Win 7 (solía funcionar bien con XP, etc.) y estoy tratando de encontrar una forma de desactivar 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% 

A continuación, elimine la tarea% taskname% cuando se inicie% service%

nssm es bastante bueno. Hará todo esto por ti

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

net stop net start

y agregue el archivo al progtwigdor con su intervalo de tiempo deseado

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