2011-02-01 13 views
46

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

Así que ejecutar la aplicación, así:

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

Bastante que se explica uno mismo, y luego llegué a services.msc y e iniciar el servicio, pero cuando lo hago me sale el siguiente mensaje:

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

Mi código es el siguiente manera:

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() Acabo de cambiar la variable running a false;

¿Qué necesitaría hacer para que el servicio activo constantemente, ya que tendría que ser el control de la red que necesito para rastrear los 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 del ThreadWorker tengo ProxyEventLogger.WriteEntry("Main thread entered") que no se dispara.

+0

'Tema = new Thread (ThreadWorker)' no funcionará –

+0

funciona perfectamente bien, ¿por qué pensaste que sería un fracaso? – RobertPitt

Respuesta

117

La devolución de llamada OnStart() debe devolverse oportunamente, por lo que querrá iniciar un hilo donde se realizará todo su trabajo. Yo recomendaría añadiendo los siguientes campos a su clase:

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

El campo _thread llevará a cabo una referencia al objeto System.Threading.Thread se crea en el OnStart() de devolución de llamada. El campo _shutdownEvent contiene una construcción de eventos a nivel de sistema que se usará para indicarle a la secuencia que deje de ejecutarse al apagar el servicio.

En la devolución de llamada OnStart(), cree y comience su hilo.

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

se 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 usted no pone nada en esta función, el hilo se pondrá en marcha y luego se apagará inmediatamente, así que hay que poner un poco de lógica en la que hay que básicamente se mantenga el hilo con vida mientras usted 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 bucle while comprueba la ManualResetEvent para ver si se "set" 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 devolución de llamada OnStop() de su servicio de Windows, desea indicarle a la cadena que deje de funcionar. Esto es fácil usando el _shutdownEvent.

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

Espero que esto ayude.

+0

Gracias por eso, lo comprendí todo y ahora funciona como esperaba :) – RobertPitt

+4

Me alegra ayudar. Por lo que vale, tengo un par de tutoriales SO detallados que muestran (1) cómo tener su propio registro en el Visor de eventos (http://stackoverflow.com/questions/593454/easiest-language-for-creating -a-windows-service/593803 # 593803) y (2) cómo instalar/desinstalar su servicio sin requerir InstallUtil.exe (http://stackoverflow.com/questions/1195478/how-to-make-a-net- windows-service-start-right-after-the-installation/1195621 # 1195621). –

+0

Sí, muchas gracias por su ayuda, ya había leído su primer artículo en mi búsqueda para la victoria, si desea ver mi código lo publiqué aquí y dejé un comentario sobre en qué etapa estoy. http://pastebin.com/t8QQzXC9 – RobertPitt

0

¿Por qué no crea un nuevo proyecto en su 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.

+1

Esto es parcialmente una experiencia de entrenamiento y preferiría aprender cómo se hace desde abajo. – RobertPitt

+0

Me atrevería a decir que incluso para la formación (especialmente para la formación?) Lo mejor sería aprender cómo VS crea el andamio para un servicio de Windows y luego puede aprender por qué funciona y cómo funciona. En lugar de ir de abajo hacia arriba, lo cual, como descubres, es mucho más frustrante. –

+0

Esto es cierto, el hecho de que el punto es discutible, pero ese no es el caso aquí. Esta aplicación se ha logrado en un 60% y tal vez en mi próxima aplicación comenzaré en la plantilla del servicio de Windows. – RobertPitt

6

Debe 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:

trate de poner un System.Diagnostics.Debugger.Launch() en su OnStart para ver lo que está sucediendo (y poner un punto de interrupción en ThreadWorker). Recomiendo encapsular esto en #if DEBUG para asegurarse de que no se implemente.

acabo también se dio cuenta de que usted no da su Thread un nombre:

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

¿Debería haber algún código de retorno, como 'return 0' o' return false', y un hilo estaría bien también? – RobertPitt

+0

No; el controlador de eventos 'OnStart' devuelve nulo. Siempre que salga dentro de un marco de tiempo razonable (aproximadamente un minuto, creo), el controlador de servicio estará contento. –

+0

Lo intentaré. – RobertPitt

2

Ciertamente no añadir un bucle while en el método OnStart. Esto le dirá al sistema operativo que el servicio no se ha iniciado 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.

Como alternativa, 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, se puede obtener un ejemplo esqueleto here.

1

Código de muestra demostrado mediante una aplicación de consola. Esperamos 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(); 
    } 


    /// <summary> 
    /// Triggers a cancellation event for stopping the service in a timely fashion. 
    /// </summary> 
    private static void ScheduledStop() 
    { 
     while (!_shutdownEvent.WaitOne(0)) 
     { 
      if (workcounter == 10) 
      { 
       _cancellationTokenSource.Cancel(); 
      } 
     } 
    } 

    /// <summary> 
    /// Represents a long running Task with cancellation option 
    /// </summary> 
    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.. 
      } 

     } 
    } 
} 
Cuestiones relacionadas