En fin, veamos una manera sencilla para poder debuguear un Windows Service.
Cuando creamos un proyecto de este tipo, lo primero que notaremos es la flamante clase Program en el archivo Program.cs con el método Main que es el punto de entrada de la aplicación. Desde aquí veremos que se llama a ServiceBase.Run que nos permite ejecutar una o varias instancias de nuestro servicio windows dentro de un mismo proceso. Por default, el código que aquí aparece correrá una sola instancia.
Pero hay un problema, el método ServiceBase.Run no funcionará en un ambiente de DEBUG debido a que este método registra el ejecutable en el Service Control Manager quien ejecuta un comando de start sobre nuestro servicio. En fin, no sería una solución agradable poder hacer un IF que nos permita conocer si estamos en DEBUG o no? Bueno, miremos el siguiente pedazo de código:
#if (!DEBUG)
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new MyService()
};
ServiceBase.Run(ServicesToRun);
#else
MyService service = new MyService();
service.Initiate();
System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite);
#endif
No estoy inventando sintaxis. Estas instrucciones antepuestas con un # son lo que se llaman Directivas de Preprocesamiento que nos permiten establecer qué codigo debe ser compilado en tiempo de RELEASE, además de otras cosas útiles que pueden chusmear en el link.
En nuestro caso lo que estamos haciendo es preguntar por la variable DEBUG (ahora la vamos a explicar también, aunque es bastante obvia) y "expandir" nuestro código en base a eso. Si corremos el Windows Service desde el IDE en configuración DEBUG ingresaremos a nuestro método Initiate de nuestro servicio, sin pasar por el OnStart ni por el ServiceBase. Para que esto nos sea útil tenemos que agregar un par de cosas a nuestro servicio. No, el método Initiate no existe en tu servicio, lo puse yo.
Veamos antes que todo lo de la variable DEBUG. Esta es simplemente una variable definida por código que no manejamos nosotros, que nos indica si estamos en DEBUG o no. Bastante simple eh? Entonces podríamos agregar interesantes códigos que sólo se ejecuten en nuestras depuraciones.
Ahora, esto así como está no funciona porque ese método Initiate no existe. Veamos qué le hice a la clase. Agregué un método Initiate que llamo tanto desde mi código de DEBUG como desde mi OnStart en el servicio. Entonces queda algo así:
protected override void OnStart(string[] args)
{
Initiate();
}
Como podrán entender, simplemente puse toda mi lógica de inicialización en el Initiate en vez de en el OnStart y nada más. No podemos llamar a OnStart directamente porque éste método es Protected. Como nota aparte, noten que el OnStart recibe un array de strings como parámetro. Éstos son argumentos que puede enviar el Service Control Manager a nuestro servicio. Puede resultarles interesante jugar con esto.
Fun Debugging!
No comments:
Post a Comment