Crear un servicio de Windows con Net Core 3.0

Portada

En las últimas semanas, estuve trabajando en el mantenimiento de servicios de Windows y un día quise crear uno pero no supe cómo. Buscando soluciones rápidas, me encontré con varias maneras de hacerlo y la que te voy a enseñar es, para mi, la más sencilla de todas para crear un servicio de Windows con NET Core 3.0.

Contenido:

¿Que es un servicio de Windows?

Los servicios de Windows, anteriormente conocidos como servicios NT, le permiten crear aplicaciones de larga ejecución que se ejecutan en sesiones propias de Windows y en segundo plano. Estos servicios se pueden iniciar automáticamente al arrancar el equipo, se pueden pausar y reiniciar, y no muestran ninguna interfaz de usuario

Worker Service

Los Worker Services son servicios que se especializan en realizar tareas de larga duración, como por ejemplo, los servicios de Windows o los “demonios” de linux.

Cuando creamos un nuevo proyecto, a partir de NET Core 3.0, tenemos disponible la plantilla de Worker Service, pero la realidad es que existen desde NET Core 2.2.

Creando nuevo proyecto con la plantilla Worker Service.

En esta plantilla nos vamos a encontrar con una aplicación de consola que tiene solamente 2 clases: Program.cs y Worker.cs.

Si vemos la clase Worker, vemos que simplemente esta implementado el método ExecuteAsync(). En ese método, es donde se ejecuta la tarea🔨, y en este caso, realiza un bucle, sin parar, imprimiendo la fecha y hora actual🕓 hasta que la tarea se cancele.

Si ejecutamos el proyecto veremos algo parecido a lo siguiente.

Worker Service ejecutándose .

De Simple Consola A Servicio de Windows.

Muchas de las otras alternativas para crear un servicio de Windows consisten en realizar configuraciones, tanto en el Regedit como en el uso de user32.dll, para que el servicio se adapte al ecosistema de Windows Services 😒 . Otras alternativas, omitían esas configuraciones utilizando librerías de terceros 😢.

Y si te dijera que ya existe un método, que no es de un tercero, que si lo implementamos hace toda esta configuración por nosotros ¿me crees?🤯

Pues si existe, se llama UseWindowsService() 😍, y para usarlo hay que realizar 2 pasos.

Primero, hay que instalar el paquete de Nuget Microsoft.Extensions.Hosting.WindowsServices.

Instalando Microsoft.Extensions.Hosting.WindowsServices .

y por último, en la clase Program, llamarlo.

!Listo, esa era toda la configuración que necesitábamos!

Con este mismo código, así como está, también podríamos crear un servicio de Linux, pero eso es historia para otro artículo. 😉

Y además con ese mismo método de extensión podríamos ejecutar en un servicio de windows, una aplicación de Asp.NET Core. ✨

Visor de Eventos De Windows

Si vamos a crear un servicio de Windows me parece apropiado que usemos el Event Viewer para registrar los logs de los eventos que ocurren en nuestro servicio.

Para esto hay que tener en cuenta 2 términos: LogName y SourceName. LogName es el nombre que tendrá nuestro registro, en donde se guardan los eventos, y SourceName u Origen sera el nombre de la aplicación que origina los eventos. En un registro, varios Orígenes pueden guardar eventos.

Hacer que nuestro servicio de Windows guarde registros en el Event Viewer es cuestión de solo 2 configuraciones ( ConfigureLogging , Configure<EventLogSettings> ).

Para poder crear un nuevo registro en el Event Viewer se necesitan permisos de administrador. Entonces, se va a crear el registro recién cuando iniciemos nuestro servicio de Windows que vamos a montar ahora mismo.

Creando El Servicio de Windows

Esto nos va a llevar 4 simples pasos. 😱

Paso 1

Primero, vamos a publicar nuestro proyecto en la carpeta que más nos guste.

Publicando el proyecto.

Paso 2

Segundo, vamos a abrir una consola (cmd, powershell, etc) con permisos de administrador.

Abriendo PowerShell como Administrador.

Paso 3

Tercero, escribiremos el siguiente comando.


sc.exe create [Nombre del servicio] binpath=[Dirección completa del ejecutable] start= auto

Ejemplo:


sc.exe create MyWindowsWorkerService binpath= c:\Temp\WorkerService\WorkerService1.exe start= auto
El comando nos devolvió el mensaje “CreateService CORRECTO”.

Paso 4

Cuarto, abrimos Servicios, buscamos el nombre de nuestro servicio y le damos Iniciar.

Nuestro servicio de Windows, ‘MyWindowsWorkerService’, fue creado exitosamente.

Al iniciar el servicio vamos al Event Viewer para confirmar que está guardando los eventos en nuestro logs.

En el Visor de Eventos se creó el registro con el LogName ‘MyLogs’ y se fueron guardando eventos del Origen ‘MyWindowsWorkerService’

¿Como fue que creamos el servicio de Windows realmente?

Antes de terminar este articulo, me gustaría hacer un breve repaso de todo lo que fuimos haciendo.

Vale aclarar que sin el método UseWindowsService(), habrían muchos más pasos y más difíciles de explicar. Les recomiendo ver el código fuente de este método aquí 👈.

En el proyecto del Worker Service vemos que la clase Worker hereda de BackgroundService. Esta es una clase abstracta que lo único que hace es llamar al método ExecuteAsync() y esperar a que finalice. Pueden ver el código fuente aquí 👈.

Lo último que agregamos fue la configuración para poder escribir logs en el Event Viewer. Esto se podría realizar sin necesidad de implementar la clase EventLogLoggerProvider, ya que nos podríamos arreglar con la clase EventLog, pero con estas implementaciones podemos hacer uso del ILoggerFactory de NET Core. El código fuente de lo utilizado se encuentra aqui 👈.