Servicio de Windows para ejecutar constantemente

He creado un servicio de Windows llamado ProxyMonitor y estoy actualmente en la etapa en que el servicio se instala y desinstala de la manera que lo deseo.

Así que ejecuto la aplicación de esta manera:

C:\\Windows\\Vendor\\ProxyMonitor.exe /install 

Bastante auto explicativo, y luego llegué a services.msc y comencé el servicio, pero cuando hago esto obtengo el siguiente mensaje:

El servicio Proxy Monitor en la computadora local se inició y luego se detuvo. Algunos servicios se detienen automáticamente si no hay trabajo que hacer, por ejemplo, los Registros de rendimiento y los Servicios de alertas

Mi código se ve así:

 public static Main(string[] Args) { if (System.Environment.UserInteractive) { /* * Here I have my install logic */ } else { ServiceBase.Run(new ProxyMonitor()); } } 

Y luego dentro de la clase ProxyMonitor tengo:

 public ProxyMonitor() { } protected override void OnStart(string[] args) { base.OnStart(args); ProxyEventLog.WriteEntry("ProxyMonitor Started"); running = true; while (running) { //Execution Loop } } 

y onStop() simplemente cambio la variable en running a false ;

¿Qué tendría que hacer para que el Servicio esté constantemente activo, ya que necesitaría monitorear la red para rastrear cambios, etc.


Actualización: 1

 protected override void OnStart(string[] args) { base.OnStart(args); ProxyEventLog.WriteEntry("ProxyMonitor Started"); Thread = new Thread(ThreadWorker); Thread.Start(); } 

Dentro de ThreadWorker tengo ProxyEventLogger.WriteEntry("Main thread entered") que no se dispara.

La callback de OnStart() debe regresar oportunamente, por lo que querrá iniciar un hilo donde se realizará todo su trabajo. Yo recomendaría agregar los siguientes campos a su clase:

 using System.Threading; private ManualResetEvent _shutdownEvent = new ManualResetEvent(false); private Thread _thread; 

El campo _thread contendrá una referencia al objeto System.Threading.Thread creado en la callback OnStart() . El campo _shutdownEvent contiene una construcción de eventos de nivel de sistema que se usará para _shutdownEvent la _shutdownEvent que deje de ejecutarse al apagar el servicio.

En la callback de OnStart() , crea e inicia tu hilo.

 protected override void OnStart(string[] args) { _thread = new Thread(WorkerThreadFunc); _thread.Name = "My Worker Thread"; _thread.IsBackground = true; _thread.Start(); } 

Necesita una función llamada WorkerThreadFunc para que esto funcione. Tiene que coincidir con la firma del delegado System.Threading.ThreadStart .

 private void WorkerThreadFunc() { } 

Si no pone nada en esta función, el hilo se iniciará y luego se apagará de inmediato, por lo que tiene que poner algo de lógica allí que básicamente mantenga el hilo vivo mientras hace su trabajo. Aquí es donde el _shutdownEvent es útil.

 private void WorkerThreadFunc() { while (!_shutdownEvent.WaitOne(0)) { // Replace the Sleep() call with the work you need to do Thread.Sleep(1000); } } 

El ciclo while comprueba el ManualResetEvent para ver si está “configurado” o no. Dado que inicializamos el objeto con false arriba, esta comprobación devuelve falso. Dentro del ciclo, dormimos durante 1 segundo. Deberá reemplazar esto con el trabajo que necesita hacer: supervisar la configuración del proxy, etc.

Finalmente, en la callback OnStop() de su Servicio de Windows, desea OnStop() la OnStop() que deje de ejecutarse. Esto es fácil de usar con _shutdownEvent .

 protected override void OnStop() { _shutdownEvent.Set(); if (!_thread.Join(3000)) { // give the thread 3 seconds to stop _thread.Abort(); } } 

Espero que esto ayude.

OnStart salir de su controlador OnStart para que el controlador de servicio se dé cuenta de que su servicio realmente se ha iniciado. Para que funcione como lo desee, podría iniciar un temporizador que funcione a un intervalo y procese cuando marque.

Editar:

Intente poner un System.Diagnostics.Debugger.Launch () en su OnStart para ver qué está sucediendo (y ponga un punto de interrupción en ThreadWorker ). Recomendaría #if DEBUG esto en #if DEBUG para asegurarme de que no se implemente.

También me di cuenta de que no le das un nombre a tu Thread :

  Thread myThread = new Thread(ThreadWorker); myThread.Start(); 

Ciertamente, no agregar un bucle while en el método OnStart . Esto le dirá al sistema operativo que el servicio no se inició porque no pudo salir de manera segura del método OnStart . Normalmente creo un Timer que está habilitado en el método OnStart . Luego, en el método Ticks , llamo al método necesario para que la aplicación se ejecute.

Alternativamente, puede hacer lo siguiente:

 // The main entry point for the process static void Main() { System.ServiceProcess.ServiceBase[] ServicesToRun; ServicesToRun = new System.ServiceProcess.ServiceBase[] { new WinService1() }; System.ServiceProcess.ServiceBase.Run(ServicesToRun); } 

Para obtener más información acerca de los Servicios de Windows, puede obtener un ejemplo de esqueleto aquí .

Código de muestra demostrado usando una aplicación de consola. espero que esto ayude …

  class Program { private static CancellationTokenSource _cancellationTokenSource; private static ManualResetEvent _shutdownEvent = new ManualResetEvent(false); private static Thread _serviceStartThread; private static Thread _serviceStopThread; private static int workcounter = 0; static void Main(string[] args) { _cancellationTokenSource = new CancellationTokenSource(); _serviceStartThread = new Thread(DoWork); _serviceStopThread = new Thread(ScheduledStop); StartService(); StopService(); } private static void StartService() { _serviceStartThread.Start(); } private static void StopService() { _serviceStopThread.Start(); } ///  /// Triggers a cancellation event for stopping the service in a timely fashion. ///  private static void ScheduledStop() { while (!_shutdownEvent.WaitOne(0)) { if (workcounter == 10) { _cancellationTokenSource.Cancel(); } } } ///  /// Represents a long running Task with cancellation option ///  private static void DoWork() { while (!_shutdownEvent.WaitOne(0)) { if(!_cancellationTokenSource.Token.IsCancellationRequested) { workcounter += 1; Console.Write(Environment.NewLine); Console.Write("Running...counter: " + workcounter.ToString()); Thread.Sleep(1000);//Not needed, just for demo.. } else { Console.Write(Environment.NewLine); Console.Write("Recieved cancellation token,shutting down in 5 seconds.. counter: " + workcounter.ToString()); _shutdownEvent.Set(); Thread.Sleep(5000);//Not needed, just for demo.. } } } } 

¿Por qué no creas un nuevo proyecto en tu solución del tipo Servicio de Windows? Esto configura todas las estructuras que necesita implementar, incluidos los controladores para los eventos de inicio / detención del servicio.