42
protected override void OnStart(string[] args) 
{ 
    AppDomain.CurrentDomain.UnhandledException += 
     new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException); 

    Thread.Sleep(10000); 

    throw new Exception(); 
} 

void CurrentDomain_UnhandledException(object sender, 
             UnhandledExceptionEventArgs e) 
{ 
} 

Adjunté un depurador al código anterior en mi servicio de Windows, estableciendo un punto de interrupción en CurrentDomain_UnhandledException, pero nunca se golpeó. La excepción aparece diciendo que no se ha manejado, y luego el servicio se detiene. Incluso traté de poner algún código en el controlador de eventos, en caso de que se optimizara.¿Cómo puedo configurar el manejo .NET UnhandledException en un servicio de Windows?

¿No es esta la forma correcta de configurar el control de excepciones no controladas en un servicio de Windows?

Respuesta

2

Simplemente curioso, ¿qué intentas lograr: evitar fallar el servicio o informar de errores?

Para informar, creo que su mejor opción es agregar declaraciones try/catch de nivel superior. Puede tratar de registrarlos en el registro de eventos de Windows y/o en un archivo de registro.

También puede establecer la propiedad ExitCode en un valor distinto de cero hasta que finalice correctamente el servicio. Si el administrador del sistema inicia su servicio desde el panel de control de Servicios, y su servicio se detiene repentinamente con un código de salida distinto de cero, Windows puede mostrar un mensaje de error con la descripción del error.

+0

Depuración. Intenté capturar todas las excepciones, pero uno se está escapando de alguna manera. Pensé que esta sería una solución más manejable. –

+0

¿Está sucediendo la excepción en OnStart o OnStop? ¿Tiene alguna otra información sobre la excepción? –

9

En un servicio de Windows, NO desea ejecutar muchos códigos en el método OnStart. Todo lo que desea es el código para iniciar su cadena de servicio y luego regresar.

Si lo hace, puede manejar bien las excepciones que suceden en su cadena de servicio.

p. Ej.

public static void Start() 
{ 
    AppDomain currentDomain = AppDomain.CurrentDomain; 
    currentDomain.UnhandledException += new UnhandledExceptionEventHandler(currentDomain_UnhandledException); 

    running = true; 
    ThreadStart ts = new ThreadStart(ServiceThreadBody); 
    thread = new Thread(ts); 
    thread.Name = "ServiceThread"; 
    thread.Priority = ThreadPriority.BelowNormal; 
    thread.Start(); 
} 
+0

Recientemente he encontrado un sitio donde mi servicio aún se ejecuta pero no procesa ... Estoy empezando a pensar que puede deberse a excepciones "tragadas". ¿Te preguntas si tienes alguna idea sobre mi problema? http://stackoverflow.com/questions/41618324/windows-service-runs-but-stops-processing-after-two-days –

4

Conozca este hilo es un poco viejo, pero pensé que sería útil agregar algunos comentarios basados ​​en la experiencia personal en el desarrollo de servicios de Windows en .NET. El mejor enfoque es evitar desarrollar bajo el Administrador de control de servicios todo lo que pueda - para esto necesita un arnés simple que imita la forma en que se inician los servicios, algo que puede crear una instancia de su clase de servicio (que ya derivado de ServiceBase) y llame a sus métodos OnStart, OnStop, etc. Este arnés puede ser una aplicación de consola o una aplicación de Windows como lo desee.

Esta es prácticamente la única forma que he encontrado de depurar problemas de arranque del servicio en .NET: la interacción entre su código, Visual Studio y el verdadero Service Control Manager simplemente hace que el proceso sea imposible.

HTH.

+0

+1: Implementa toda tu lógica en una biblioteca separada y llámala de tu servicio. Llame a la misma biblioteca desde una aplicación de consola para fines de desarrollo/depuración. –

+2

Me gusta su enfoque, pero no es la única forma de solucionar problemas de inicio del servicio. Lo que hago, especialmente cuando depuro servicios en el entorno de producción, es configurar WinDbg para: 1. adjuntarme al servicio en el momento en que se inicia su proceso de host, y 2. abrir un puerto de escucha (necesario para superar el aislamiento del servicio). Entonces, es posible comenzar a depurar usando otra instancia de WinDbg que se ejecuta bajo su sesión de usuario. (Una llamada configurable a "RequestAdditionalTime" como primer enunciado, o una configuración del Registro, ayuda a superar el límite de tiempo que el SCM enfoca en el tiempo de inicio del servicio) –

51

He llegado a este hilo bastante tarde, pero pensé que podría valer la pena proporcionar una explicación que ninguna de las otras respuestas da. El motivo por el que el controlador CurrentDomain_UnhandledException no aparece en el ejemplo del código OP es que se llama al método OnStart en respuesta a un comando de Inicio del Administrador de control de servicios de Windows (el comando se recibe y se envía a este método por el marco Implementación de ServiceBase); cualquier excepción lanzada por OnStart se maneja en la clase base, se registra en el registro de eventos y se traduce en un código de estado de error devuelto al SCM. Entonces la excepción nunca se propaga al controlador de excepción no controlada de AppDomain.

Creo que encontraría que una excepción no controlada lanzada desde un subproceso de trabajo en su servicio sería atrapada por el controlador CurrentDomain_UnhandledException.

+0

Parece que es el método ServiceQueuedMainCallback en ServiceBase el que causa este comportamiento. –

2

Cuando estaba trabajando en mi propio servicio de Windows, se detenía de forma bastante extraña. Pensé que era por una excepción sin manos. Por el momento estoy atrapando excepciones sin manos en el archivo de texto. En primer lugar, debe crear el nuevo archivo ServiceLog.txt en las ubicaciones C debido a las anotaciones de registro en el archivo de texto. Con la codificación de abajo obtuve todas las excepciones sin mano con ellos los números de línea.

using System.Security.Permissions; 
using System.IO; 

[SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlAppDomain)] 
    protected override void OnStart(string[] args) 
    { AppDomain currentDomain = AppDomain.CurrentDomain; 
     currentDomain.UnhandledException += new UnhandledExceptionEventHandler(MyHandler); 
     ... 
     Your codes... 
     .... 
    } 
    void MyHandler(object sender, UnhandledExceptionEventArgs args) 
    { 
     Exception e = (Exception)args.ExceptionObject; 
     WriteToFile("Simple Service Error on: {0} " + e.Message + e.StackTrace); 
    } 
    private void WriteToFile(string text) 
    { 
     string path = "C:\\ServiceLog.txt"; 
     using (StreamWriter writer = new StreamWriter(path, true)) 
     { 
      writer.WriteLine(string.Format(text, DateTime.Now.ToString("dd/MM/yyyy hh:mm:ss tt"))); 
      writer.Close(); 
     } 
    } 
Cuestiones relacionadas