2011-08-10 18 views
16

Tengo dificultades para tratar de determinar la causa de un tiempo de espera en un servicio de Windows que he creado con C#. Pasé un tiempo considerable mirando varias publicaciones y temas sobre el tema, pero no estoy seguro de qué más probar.C# Servicio de Windows Tiempo de espera en el inicio

¿Cuál es el problema?

A veces, en ciertas máquinas que ejecutan mi servicio de Windows, no se inicia correctamente después de que la máquina se haya reiniciado. Recibo los mensajes comunes de EventLog sobre el Servicio que no se inicia de manera oportuna y que se agotó el tiempo después de 30000 milisegundos. Las máquinas con Windows Server 2003 parecen ser el patrón más común, pero no siempre están aisladas solo con este sistema operativo. Por ejemplo, funciona perfectamente bien en otras máquinas W2K3.

La falla de inicio puede ser bastante aleatoria ya que a veces se iniciará y otras veces fallará, por lo que es muy difícil reproducir el problema bajo demanda. También estoy usando Log4Net para detectar errores y registrarlos en RollingFileAppender. Sin embargo, cuando el servicio no se inicia, nunca se crea un archivo de registro y no se guarda la información de registro. Es como si mi cadena de entrada de Servicio estuviera bloqueada y no se llamara.

Otros detalles:

  1. El servicio de Windows está escrito en C# y .Net 2.0 utiliza
  2. No existen otras dependencias de servicio de mi servicio cuando instalado.
  3. El service exe es una versión de lanzamiento sin firma o autentificación firmando.
  4. El método OnStart se ejecuta lo más rápido posible al crear un subproceso y al iniciar dicho subproceso. No se lleva a cabo ninguna otra inicialización dentro de OnStart.
  5. Cuando el servicio realmente no se inicia, abrir la lista de servicios e iniciarlo manualmente funciona siempre y el servicio se inicia en probablemente menos de un segundo.

Tengo el siguiente código agregado a mi Program.cs que incluye el punto de entrada principal para el servicio. Me conecto a un evento UnhandledException en el dominio actual y estoy usando log4net para registrar cualquier error no controlado También hay un try/catch alrededor del ServiceBase.Run en el caso de que de alguna manera salga a borbotones para poder registrar ese error.

static void Main() 
{ 
    ServiceBase[] ServicesToRun; 
    ServicesToRun = new ServiceBase[] 
    { 
     new SchedulerService() 
    }; 

    AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException); 

    try 
    { 
     ServiceBase.Run(ServicesToRun); 
    } 
    catch (Exception ex) 
    { 
     Log.Fatal("Unhandled Service Exception", ex); 
    } 
} 

private static log4net.ILog _log = null; 
static log4net.ILog Log 
{ 
    get 
    { 
     if (_log == null) 
     { 
      if (!log4net.LogManager.GetRepository().Configured) 
      { 
       log4net.Config.XmlConfigurator.Configure(); 
      } 

      _log = log4net.LogManager.GetLogger(typeof(Program)); 
     } 
     return _log; 
    } 
} 

static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) 
{ 
    Exception ex = e.ExceptionObject as Exception; 
    if (ex == null) ex = new Exception(e.ExceptionObject.ToString()); 

    Log.Fatal("Unhandled Service Exception", ex); 
} 

El código en mi aplicación ServiceBase heredada es el siguiente:

protected override void OnStart(string[] args) 
{ 
    Thread serviceThread = new Thread(new ThreadStart(BackgroundStart)); 
    serviceThread.IsBackground = true; 
    serviceThread.Start(); 
} 

private void BackgroundStart() 
{ 
    //Initialize and start worker objects to perform monitoring... 
    //<Snip> 
} 

Mi aplicación log4net utiliza una ConsoleAppender y una RollingFileAppender donde se almacenan sus datos de configuración en el App.config.

En este momento no estoy seguro de qué más probar. Si necesita más información, avíseme.

Gracias.

Actualización: Sólo para actualizar todos, voy a probar algunas de las sugerencias, tales como el registro en el EventLog directa o un archivo en lugar de Log4net para ver si esa es la causa. También intentaré configurar generatePublisherEvidence en app.config en false. Estoy esperando un tiempo de inactividad apropiado para acceder al servidor del cliente y probar estas cosas.

+0

¿Ha intentado agregar declaraciones de depuración en su código para saber hasta qué punto se está iniciando el servicio? –

+0

También podría intentar habilitar la depuración interna de log4net para obtener posiblemente un poco más de información: http://logging.apache.org/log4net/release/faq.html#How%20do%20I%20enable%20log4net%20internal%20debugging% 3F –

+2

Una posibilidad es que su marco de trabajo de registro es lo que está colgando y esto está ocultando el verdadero problema, especialmente porque usted dice que nada se registra cuando se bloquea. – alun

Respuesta

1

En general, engendrar un hilo de fondo de OnStart es lo correcto.

Para la resolución de problemas, puede tratar de darle a su servicio más tiempo de inicio llamando al RequestAdditionalTime desde OnStart. Además, es posible que desee verificar si se han escrito mensajes en el EventLog de Windows (registro "Aplicación", el origen debe ser su nombre de servicio).

2

Algunas cosas para probar:

  • mensajes de registro Agregar a la parte superior de Main(), antes de ServiceBase.Run(), etc. Suponiendo que se obtiene un archivo de registro, ¿cómo estas marcas de tiempo en comparación con el registro de sucesos de Windows?

  • Cree un nuevo servicio con el Asistente de proyecto nuevo y despliéguelo tal como está. En las máquinas problemáticas, ¿comienza confiablemente?

  • Obtenga process monitor y mire un inicio normal. Busque cualquier red o archivo I/O inesperado.

  • Asegúrese de que su SchedulerService no hace ningún trabajo en el constructor y no tiene ninguna dependencia inicializada estáticamente.

  • Establezca las opciones de Recuperación para reiniciar en la primera falla. ¿Eso funciona de manera confiable?

1

También sospecho que log4net está colgando de alguna manera. Quizás el disco donde se creará el registro aún no está listo cuando la máquina está arrancando. ¿Has intentado comenzar tu servicio retrasado?

enter image description here

+0

Lo sentimos, descubrimos que esta opción solo está disponible en Vista y versiones posteriores. Pero es posible que desee mover la creación del registrador al método Principal y retrasar el inicio del servicio hasta que el registrador pueda crearse correctamente. –

0

Desde log4net no está diseñado para ser (in their words) un sistema de registro fiable, pensé que era una buena práctica para escribir las excepciones no controladas en el registro de eventos (así como a su registro), en especial con los servicios.

6

Solucioné un problema similar al desactivar la generación de evidencia del editor en el archivo de configuración. El servicio tampoco tenía firma autenticada, pero al agregar la siguiente línea se corrigió de inmediato el problema en la máquina donde se reprodujo de forma consistente.

<runtime> 
    <generatePublisherEvidence enabled="false" /> 
</runtime> 

También recomendado en this MSDN source:
"Recomendamos que los servicios utilizan el elemento para mejorar el rendimiento de inicio El uso de este elemento también puede ayudar a evitar retrasos que pueden causar un tiempo de espera y la cancelación del inicio del servicio.. "

Cuestiones relacionadas