Crear e instalar un servicio Windows

Estos días he estado trabajando con servicios Windows, los cuales se utilizan para realizar operaciones en background. Una de las principales ventajas de los mismos es que tenemos la posibilidad de ejecutarlos sin necesidad de tener un usuario logado en el sistema.

En este post voy a mostrar la forma de crear un proyecto con una pequeña demo y varias formas para instalarlo.

Creación del proyecto

Creamos un proyecto del tipo de Windows Service. En este post lo llamaré CheckerWindowsService.

Cuando carga la plantilla de Visual Studio, vemos que tenemos un nuevo archivo llamado Service1.cs y el típico Program.cs que acompaña a las aplicaciones de consola. Si accedemos al primero de ellos, nos mostrará la parte de diseño que básicamente es un fondo gris 😀 Si pulsamos sobre ella con el botón derecho y hacemos clic en View Code veremos la siguiente estructura:

 

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text; 

namespace CheckerWindowsService
{
    public partial class Service1 : ServiceBase
    {
        public Service1()
        {
            InitializeComponent();
        } 

        protected override void OnStart(string[] args)
        {
        } 

        protected override void OnStop()
        {
        }
    }
} 

La clase Service1 debe heredar de ServiceBase para obtener todos los métodos y propiedades relacionadas con los servicios Windows. En esta plantilla se muestran los métodos que normalmente se sobrescriben: OnStart donde insertaremos el código que queremos que se ejecute nada más iniciar el servicio y OnStop en el caso de que el mismo sea parado. Para este ejemplo, voy a renombrar la clase Service1.cs a CheckerService.cs.

Implementación

Lo primero que debemos modificar son las propiedades del archivo CheckerService.cs

 

Por nombrar algunas de las propiedades más utilizadas, AutoLog se utiliza para permitir que el servicio registre o no los inicios, paradas, etcétera en el visor de eventos del sistema (opción por defecto). CanPauseAndContinue nos da la posibilidad de pausar y continuar con la ejecución del servicio, CanStop pararlo (al hacer esta opción pasará por el método OnStop) y ServiceName donde asignamos el nombre del servicio.

En esta demo lo que vamos a hacer es que cada minuto vamos a comprobar si existe algún proceso del explorador Firefox abierto y, de ser así, vamos a finalizarlo (y si se resiste matarlo :D).  Sobre la vista de diseño pulsamos con el botón derecho y seleccionamos View Code para agregar lo siguiente:


protected override void OnStart(string[] args)
{

   var timer = new Timer { AutoReset = true, Interval = 60000 };
   timer.Elapsed += timer_Elapsed;
   timer.Start();
}

private void timer_Elapsed(object sender, ElapsedEventArgs e)
{
    var processes = Process.GetProcessesByName("firefox");

    foreach (var process in processes)
    {
       process.CloseMainWindow();

       if (!process.HasExited)
       {
            process.Kill();
            process.Close();
       }
    }
}

Añadir Instalador

Una vez que tengamos nuestro código implementado, es necesario añadir un instalador a la solución. Para ello nos ponemos en el modo diseño y con el botón derecho seleccionamos Add Installer.

En este momento se agregará una nueva clase llamado ProjectInstaller.cs con dos componentes. Hacemos clic sobre serviceInstaller1 donde indicaremos el nombre del servicio (el mismo ServiceName que en CheckerService.cs) y el tipo de inicio (Manual, Automático o Deshabilitado). Además podemos indicar el nombre a mostrar y una descripción de lo que hace la aplicación. Estos dos últimos datos serán los que se mostrarán en el listado de servicios de Windows.

Por último, si seleccionamos el otro elemento, serviceProjectInstaller1, podemos seleccionar el tipo de cuenta con la que queremos que se ejecute el servicio. En este caso, utilizaré LocalSystem para tener los permisos suficientes para matar procesos.

serviceProjectInstaller-Account

Instalación/Desinstalación

Para la instalación del servicio Windows tenemos varias alternativas:

  • Utilizar la plantilla para el proyecto del tipo Setup Project.
  • Crear instaladores con InstallShield.
  • El comando InstallUtil.exe desde la línea de comandos.

Setup Project

Adjuntamos a nuestra solución un nuevo proyecto del tipo Setup Project.

Seleccionamos el proyecto que acabamos de crear y añadimos la salida del proyecto del servicio web.

Aparecerá un cuadro de diálogo con el proyecto Windows Service por defecto donde dejaremos seleccionado Primary output y confirmamos.

En el Explorer Solution hacemos click en el botón Custom Actions Editor.

 Y aparecerá una nueva ventana donde se alojan las acciones personalizadas. Con el botón derecho añadimos una nueva como se muestra en la imagen:

Seleccionamos Application Folder.

Y por último aparecerá únicamente Primary output from CheckerWindowsService que es la que añadimos anteriormente. Pulsamos en OK y ¡Listo!

Primary-output-from-CheckerWindowsService1

Para instalarlo, compilamos nuestra solución y posteriormente el proyecto Setup Project. Seleccionamos el proyecto de instalación con el botón derecho y hacemos click en Install.

Para desinstalar la operación sería la misma pero con Unistall 😀

InstallShield

De lo poco que pude trastear con InstallShield, pude ver que las opciones de configuración son mayores que con Setup Project y te permite una mejor personalización de las instalaciones.

Si bien con Visual Studio 2010 puedes hacer uso de InstallShield Limited Edition.

Para poder crear un installer para un windows service necesitas tener al menos una versión Premium, obviamente de pago.

InstallUtil.exe

Desde la línea de comandos también podemos instalar/desinstalar un servicio Windows. El comando InstallUtil.exe se instala automáticamente con Visual Studio y podemos ejecutarlo a través de Visual Studio Command Prompt.

Instalación

InstallUtil.exe miEjecutable.exe

Desinstalación

InstallUtil.exe /u miEjecutable.exe

Espero que os sea de utilidad 😀

¡Saludos!

  • Jo con la demo … => firefox killer !!! jejej

    • jajaja 😛 Y para probarlo lo puse que se lanzara cada 5 segundos y ¡No había forma de abrir el Firefox! jejeje

      • de que forma se podria mandar a llamar al navegador predeterminado con una url especifica, cada cierto periodo de timepo?

  • Pingback: Tweets that mention Crear e instalar un servicio Windows | Return(GiS); -- Topsy.com()

  • Sen

    Jo. Empezamos bien el año. ¡Asesinando a zorritos de fuego! 🙂

    Saludos

    • Tenía que darle un poco de emoción al asunto Sen 🙂

      ¡Saludos!

  • Esteban

    Hola, Gisella. He seguido tu tutorial para crear un servicio que imprime PDFs utilizando SumatraPDF. Lamentablemente al tratar de iniciar el servicio me arroja una excepción:

    “An unhandled exception (‘System.TypeInicitalizationException’)” ocurred in nombreApp.exe [5640]”

    He probado creando la aplicación como windows form y como app de consola y funciona sin problemas; solo al crearla como servicio tengo problemas.

    ¿Crees que podrías ayudarme a encontrar una solución?

    • Hola Esteban,

      Lamento no haber podido contestar antes… 🙁 ¿Resolviste tu problema?

      ¡Saludos!

  • Cesar Verano

    Que buen post, muchas gracias, como sugerencia, y continuación a este, podrías hacer uno de las diferentes formas de depurarlo.

    Un abrazo …..

    • Gracias por tu comentario César 🙂 A ver si saco algo de tiempo y puedo hacer uno de lo que me comentas.

      ¡Saludos!

  • Tía eres una máquina. He estando siguiendo los pasos de varias web y no se me había ocurrido mirar en tu blog. Está de PUTA MADRE explicado con todos los pasos perfectos.

    MUCHÍSIMAS GRACIAS

    • Gracias por tu comentario JoseM 😀 me alegra que te haya sido de utilidad.

      Además este post fue muy criticado porque decían que era muy básico para que lo escribiera un MVP… 🙂

      ¡Saludos!

      • Pamplinas los hay en todos lado y en el mundo de desarrollo mucho más 😀

  • Mika Coello

    huy! solo leí esto y ya siento que te amo…
    Gracias!

  • Francisco Duran

    Estimada.

    Estoy programando un servicio muy similar a lo que tu has desarrollado, pero este revisa si el proceso no se esta ejectando me abre el programa.

    El problema surge que al instalar el servicio como usuario Localsystem, al momento que abre el programa no me lo muestra y dentro del administrador de tareas aparece iniciado pero con usuario System, creo que no me lo muestra porque esta con system.

    Alguna sugerencia de como resolver esto.

    Saludos.

  • Hernán

    Excelente Post si tienes la oportunidad de poner tambien usando Wix estaria genial ya que para los que usamos VS2012 ya no tenemos ese template

    Saludos!

    • Gisela

      ¡Gracias por tu comentario Hernán! La verdad es que ese tema lo tengo bastante abandonado desde que escribí sobre ello 🙂 Pero lo tendré en cuenta si vuelve a surgir … 😀

      ¡Saludos!

  • Hola estuve revisando tu tutorial y me resulta muy bueno, pero tengo una duda, soy nueva en esto . Tengo ya hecho mi proyecto en c# como hacer que este proyecto sea un servicio y a la vez crear su ejecutable. Eh estado checando varios tutoriales y muchos mencionan este timer, pero yo lo que quiero estar llamando es la ejecucion de mi proyecto, como le tengo que hacer? La verdad ando perdida 🙁

    • Hola Giseliux 440,

      Gracias por tu comentario 🙂

      No entiendo exactamente qué es lo que necesitas. El timer sirve para dos cosas: por un lado para que la aplicación no finalice y por otro para realizar la comprobación cada X tiempo. Si lo que necesitas es llamar a otra aplicación cada cierto tiempo para que ejecute una tarea, podrías hacer uso también del Timer para controlarlo, pero no sé si es exactamente lo que necesitas…

      ¡Saludos!

      • Giseliux 440

        Necesito que una aplicación que hice en c# se ejecute como un servicio e instalarlo en varias computadoras y no se cómo hacerlo, vi que empleas aquí un timer

        • Hola Giseliux 440,

          Para instalarlo puedes seguir los pasos que se indican en el apartado “Añadir un instalador”. Con ello podrás crear lo que necesitas para poder ejecutarlo en varios equipos e instalarlo como servicio.

          ¡Saludos!

          • Hola: Muchas gracias por contestarme, haré lo que me dices . Saludos

  • Hola Gisela

    Estoy tratando de hacer un servicio que este verificando un puerto especifico y automaticamente realice un proceso hasta el momento no se donde colocar el código de abrir el puerto y procesar la solicitud, gracias por tu colaboración y un saludo desde Colombia

  • Jdavydshi3

    Que tal un pregunta, como puedo hacer que el servicio solo se ejecute con el usuario administrador, el servicio esta montado en un servidor, y cada vez que se inicia sesion me inicia el servicio y solo lo necesito con la de Administrador

  • Gabriel David

    Se ha creado un nuevo servicio en Visual 2013 pero, resulta que Microsoft Windows 2012 r2 de 64 bits no me permite , diciendo que “no se encuentra” (si lo trato de desinstalar) o “este servicio ya existe ” (si se intenta instalar)

  • Jesus Castrillo

    Me ha servido un mundo, siempre he ido a “pie” para la instalacion de los servicios, una duda que tengo, espero puedas ayudarme, tengo un WPF que me permite la edicion del app.config del Windows Services, parametros como ConnectionString entre otros valores importantes para poder dar inicio al servicio, como lo puedo incluir en ese instalador sin que me afecte el mismo, desde ya muchisimas gracias *Colocando el Blog en Bookmark*

  • WaldoM

    Hola, excelente tu tutorial! 🙂

  • Adolfito Olarte

    Hola buen día una pregunta como podría hacer algo parecido pero que se ejecute lo que quiero por ejemplo a medio día y a media noche?