2009-05-03 16 views
24

Estoy tratando de construir varios servicios de Windows para hacer cosas diferentes. Por ejemplo, necesito servicios de Windows que:Varios servicios de Windows en un exe

  1. Enviar un informe diario por correo electrónico
  2. periódicamente la limpieza algo de información archivado cada 30 minutos
  3. etc.

Las tareas que necesito las ventanas Los servicios para hacer son distintos, así que no me gusta la idea de tenerlos todos en un solo servicio.

Lo que tengo hasta ahora es un proyecto en Visual Studio 2008. He creado un servicio de Windows, he configurado un temporizador en el evento OnStart (solo escribe en un archivo de texto cada 5 segundos para fines de prueba). Luego agregué un Instalador al proyecto y cuando ejecuto InstallUtil.exe, todo funciona bien.

El problema aparece cuando agrego un segundo servicio de Windows para el mismo proyecto. Configuré el código OnStart nuevamente, con la misma información de registro (ligeramente diferente para poder decir qué servicio está escribiendo en el registro). Con el segundo servicio de Windows, he cambiado el evento principal en Program.cs de:

static void Main(string[] args) 
    { 
     ServiceBase[] ServicesToRun = new ServiceBase[] 
     { 
      new Service1() 
     }; 

     ServiceBase.Run(ServicesToRun); 
    } 

a:

static void Main(string[] args) 
    { 
     ServiceBase[] ServicesToRun = new ServiceBase[] 
     { 
      new Service1(), 
      new Service2() 
     }; 

     ServiceBase.Run(ServicesToRun); 
    } 

En este momento, no hay errores en tiempo de compilación, pero el servicio Servicio2 nunca lo hace cualquier cosa ... la tarea de registro nunca se dispara.

Lo reduje al hecho de que el segundo servicio no tiene un "Instalador" asociado. Luego traté de agregar un Instalador de la manera en que lo hice con el primer servicio (es decir, hago clic con el botón derecho en el diseñador del servicio y hago clic en "Agregar instalador"). Ahora, cuando voy al archivo ProjectInstaller.cs, hay otro serviceInstaller allí (serviceInstaller2).

Ahora cuando genere el proyecto y tratar de instalar los servicios, y voy a la ventana del panel de control "Servicios", y que intenta iniciar Service1, me sale el siguiente mensaje de error:

de Windows no se pudo iniciar el servicio Service1 en la computadora local.

Error 1083: El programa ejecutable que este servicio está configurado para ejecutarse no implementa el servicio.

Aparece el mismo mensaje de error si trato de iniciar Service2 también (con la excepción de que el mensaje de error identifica Service2, por supuesto).

¿Hay algo que me falta para poder ejecutar dos servicios desde un ejecutable?

+0

¿Hay alguna razón en particular que no sea "yo quiero" que Necesita tener los servicios en un solo ejecutable? Normalmente, modularidad sería preferible, pero puede tener circunstancias atenuantes que requieren lo contrario. – bsneeze

+0

La única razón real es para facilitar la instalación y el despliegue. Todos los "servicios" son piezas de funcionalidad bastante rápidas, por lo que preferiría no tener que instalar x cantidad de servicios de Windows para pequeños fragmentos de código. –

+0

@pyrochild: estoy seguro de que hay numerosas razones para montar varios servicios en un solo ensamblaje. Donde trabajo ahora utilizamos bestias de ese diseño por cliente: hace que el software de prueba que interactúa con esos servicios sea muy sencillo. – Hardryv

Respuesta

1

Estoy construyendo algo muy similar a lo que estás pensando. Lo que he decidido hacer (hasta ahora) es tener todos mis 'servicios' (aunque no son servicios, el único 'controlador' es) implementar una interfaz particular (con las operaciones init() y execute() también como una enumeración de FRECUENCIA).

El controlador es el servicio de Windows y lee la lista de programas/dlls de un archivo de configuración xml en tiempo de ejecución y los carga en una lista y llama a su método execute() en cualquier frecuencia que definan.

En mi caso, cada programa también contiene un control de usuario que se carga en una página de pestañas del controlador que permite al usuario controlarlo/modificarlo. Voy a publicar el código si estás interesado.

No estoy seguro si eso estaba claro. De hecho, recibí la idea de otro usuario de SO que implementó algo similar, pero ahora no puedo encontrar esa publicación.

2

Tuve un problema similar hoy y logré resolverlo.

En primer lugar, me aseguré de que cada uno de los servicios tuviera una propiedad ServiceName significativa y única. El generador dio a ambos servicios el mismo nombre que no habría ayudado.

Luego eliminé y volví a generar la clase ProjectInstaller y agregué instaladores para cada una de las clases. Me aseguré de que ambos fueran instanciados en el método Main estático.

Ahora puedo instalar los dos servicios con el dll, pero desafortunadamente cuando inicio uno de los servicios parece que realiza las funciones tanto de sí mismo como del otro servicio. Es decir, ambos servicios se están ejecutando (aunque solo uno de los servicios aparece como 'Iniciado' en Computer Manager). Todavía estoy tratando de resolverlo ...

0

Tuve el mismo problema hoy y logré solucionarlo. En mi caso, solo tuve que abrir los archivos * .designer.cs de mis servicios y asegurarme de que el nombre del servicio esté configurado correctamente. Lo que es más importante, el mismo nombre debe usarse en * Installer.Designer.cs y si tiene código en * Installer.cs.

Creo que este error se produce solo por falta de coincidencia de nombres.

Esperanza esta helpds

4

supongo que ustedes ya han resuelto este, pero en el caso de que alguna otra persona lo necesita, voy a publicar una respuesta a esta cuestión, que me llevó varias horas de hoy. La solución no es agregar otro instalador de proyecto, sino un instalador de servicio, que es un componente en el instalador del proyecto. El instalador de servicios recién agregado debe tener configurado el segundo nombre de servicio.

+0

Tuve que usar los detalles aquí para decirme cómo hacer esto: https : //msdn.microsoft.com/en-us/library/zt39148a (v = vs.110) .aspx Para el perezoso: "Abra el menú contextual para la ventana del diseñador (si usa un dispositivo señalador, haga clic dentro de la ventana), y luego elija Agregar Instalador ". – wilsjd

+0

No pude entender lo que quería decir con los puntos 6 y 7. –

14

He descubierto cómo tener un solo ejecutable pero dos servicios. Cada servicio se instala en el administrador de servicios con su propio nombre y capacidad para iniciar/detener. Creo que esto es lo que quieres, ¿correcto? Esto es lo que hice:

  1. Creé un proyecto de servicio.
  2. Se agregó un segundo servicio al mismo proyecto (con un nombre de servicio único).
  3. Agregué un instalador a ambos servicios (ServiceA y ServiceB).
  4. En el archivo ProjectInstaller.Designer.vb, cambié la línea Me.Installers.AddRange para mostrar los dos instaladores del servicio. (Me.ServiceInstaller1, Me.ServiceInstaller2)
  5. En el punto de entrada principal del servicio principal (ServiceA en mi caso), establecí la variable ServicesToRun en una matriz de ServiceBase que contiene todos los servicios que quiero que se ejecute (ServiceA y ServiceB). Este es un paso importante ya que el administrador del servicio establece una propiedad en función del número de argumentos aquí, ya sea para permitir múltiples instancias del mismo exe o solo una instancia única.
  6. Agregue un proyecto de instalador y use la salida de Servicios.
  7. Agregue una acción personalizada utilizando la salida de Servicios.

Puede encontrar el código de demostración aquí:
http://code.google.com/p/multi-service-install/

Enjoy!

0

Instalar 2 servicios distintos y no relacionados en un ejecutable tiene un olor extraño para mí. Si bien es posible hacer que funcione, no lo hace bien.

Por lo que parece, debe realizar algunas tareas diferentes en varios intervalos y sus tareas pueden o no estar relacionadas. ¿Has mirado en Quartz.NET? Parece una buena opción para sus necesidades.

http://quartznet.sourceforge.net/features.html

1

que utilizan sc.exe de lograr esto fácilmente. http://support.microsoft.com/kb/251192

Por ejemplo: sc create "My Display Service Name" binpath= "c:\app\mysvc.exe --service"

Nota: todos los iguales deberían tener espacio antes de su valor como se puede ver por 'binpath'

Cuestiones relacionadas