Así que hemos creado un servicio de Windows para enviar datos a la aplicación de nuestro cliente y todo va muy bien. El cliente ha presentado una solicitud de configuración divertida que requiere dos instancias de este servicio ejecutándose en el mismo servidor y configuradas para apuntar a bases de datos separadas.
Hasta ahora no he podido hacer que esto suceda y esperaba que mis compañeros miembros de stackoverflow pudieran dar algunas pistas de por qué.
Configuración actual:
Configuré el proyecto que contiene el servicio de Windows, lo llamaremos AppService de ahora en adelante, y el archivo ProjectInstaller.cs que maneja los pasos de instalación personalizados para establecer el nombre del servicio basado en una clave en App.config así :
this.serviceInstaller1.ServiceName = Util.ServiceName;
this.serviceInstaller1.DisplayName = Util.ServiceName;
this.serviceProcessInstaller1.Account = System.ServiceProcess.ServiceAccount.LocalSystem;
En este caso, Util es solo una clase estática que carga el nombre del servicio del archivo de configuración.
De aquí en adelante, he probado dos formas diferentes de instalar ambos servicios y ambos han fallado de manera idéntica.
La primera forma fue simplemente instalar la primera copia del servicio, copiar el directorio instalado y renombrarlo, y luego ejecutar el siguiente comando después de modificar la configuración de la aplicación para cambiar el nombre del servicio deseado:
InstallUtil.exe /i AppService.exe
Cuando eso no funcionó, intenté crear un segundo proyecto de instalación, edité el archivo de configuración y construí el segundo instalador. Cuando ejecuté el instalador, funcionó bien, pero el servicio no aparecía en services.msc, así que ejecuté el comando anterior contra el segundo código base instalado.
En ambas ocasiones recibí el siguiente resultado de InstallUtil (solo partes relevantes):
Ejecutando una instalación transaccional.
Comenzando la fase de instalación de la instalación.
Instalando el servicio App Service Two ... Service App Service Two se ha instalado correctamente. Creando el servicio de aplicación de origen de EventLog dos en la aplicación de registro ...
Se produjo una excepción durante la fase de instalación. System.NullReferenceException: referencia de objeto no establecida en una instancia de un objeto.
Está comenzando la fase de reversión de la instalación.
Restaurando el registro de eventos al estado anterior para el App Service Two de origen. Aplicación de servicio Servicio dos se está eliminando del sistema ... Aplicación de servicio Servicio dos se eliminó correctamente del sistema.
La fase de reversión se completó con éxito.
La instalación de la transacción se completó. La instalación falló y se realizó la reversión.
Lo siento por la publicación tan larga, quería asegurarme de que haya suficiente información relevante. La pieza que hasta ahora me ha dejado perplejo es que afirma que la instalación del servicio se completa con éxito y solo después de que va a crear la fuente EventLog parece que se lanza la NullReferenceException. Entonces, si alguien sabe lo que estoy haciendo mal o tiene un mejor enfoque, sería muy apreciado.
fuente
http://journalofasoftwaredev.wordpress.com/2008/07/16/multiple-instances-of-same-windows-service/
. Puede insertar código en el instalador para obtener el nombre de servicio que desea cuando ejecuta installutil.Esta solución funcionó para mí.
fuente
[path to your exe]
tiene que ser la ruta completa y no olvides el espacio despuésbinpath=
Puede ejecutar varias versiones del mismo servicio haciendo lo siguiente:
1) Copie el archivo ejecutable y la configuración del servicio en su propia carpeta.
2) Copie Install.Exe a la carpeta ejecutable del servicio (desde la carpeta .net framework)
3) Cree un archivo de configuración llamado Install.exe.config en la carpeta ejecutable del servicio con el siguiente contenido (nombres de servicio únicos):
4) Cree un archivo por lotes para instalar el servicio con el siguiente contenido:
5) Mientras esté allí, cree un archivo por lotes de desinstalación
EDITAR:
Tenga en cuenta que si me perdí algo, aquí está la clase ServiceInstaller (ajuste según sea necesario):
fuente
Antigua pregunta, lo sé, pero tuve suerte al usar la opción / servicename en InstallUtil.exe. Sin embargo, no lo veo en la lista de ayuda incorporada.
No estoy completamente seguro de dónde leí por primera vez sobre esto, pero no lo he visto desde entonces. YMMV.
fuente
An exception occurred during the Install phase. System.ComponentModel.Win32Exception: The specified service already exists
Otra forma rápida de especificar un valor personalizado para
ServiceName
yDisplayName
es usandoinstallutil
parámetros de línea de comando.En su
ProjectInstaller
clase, anule los métodos virtualesInstall(IDictionary stateSaver)
yUninstall(IDictionary savedState)
Instale el servicio
installutil
agregando su nombre personalizado usando el/servicename
parámetro:Tenga en cuenta que si no especifica
/servicename
en la línea de comando, el servicio se instalará con los valores ServiceName y DisplayName especificados en ProjectInstaller properties / configfuente
No tuve mucha suerte con los métodos anteriores cuando usé nuestro software de implementación automatizada para instalar / desinstalar con frecuencia servicios de Windows en paralelo, pero finalmente se me ocurrió lo siguiente que me permite pasar un parámetro para especificar un sufijo al nombre del servicio en la línea de comando. También permite que el diseñador funcione correctamente y podría adaptarse fácilmente para anular el nombre completo si es necesario.
Con esto en mente, puedo hacer lo siguiente: Si llamé al servicio "Awesome Service", entonces puedo instalar una versión UAT del servicio de la siguiente manera:
InstallUtil.exe /ServiceSuffix="UAT" MyService.exe
Esto creará el servicio con el nombre "Awesome Service - UAT". Lo hemos utilizado para ejecutar las versiones DEVINT, TESTING y ACCEPTANCE del mismo servicio que se ejecutan en paralelo en una sola máquina. Cada versión tiene su propio conjunto de archivos / configuraciones; no lo he intentado para instalar varios servicios que apuntan al mismo conjunto de archivos.
NOTA: debe usar el mismo
/ServiceSuffix
parámetro para desinstalar el servicio, por lo que debe ejecutar lo siguiente para desinstalar:InstallUtil.exe /u /ServiceSuffix="UAT" MyService.exe
fuente
/ServiceSuffix="UAT"
instalador utiliza el valor que ingresa para establecer el sufijo en el servicio. En mi ejemplo, el valor pasado esUAT
. En mi escenario, solo quería agregar un sufijo al nombre existente del servicio, pero no hay ninguna razón por la que no pueda adaptar esto para reemplazar el nombre por completo con el valor que se ha pasado.Lo que hice para que esto funcione es almacenar el nombre del servicio y el nombre para mostrar en una aplicación.config para mi servicio. Luego, en mi clase de instalador, cargo app.config como un XmlDocument y uso xpath para obtener los valores y aplicarlos a ServiceInstaller.ServiceName y ServiceInstaller.DisplayName, antes de llamar a InitializeComponent (). Esto supone que aún no está configurando estas propiedades en InitializeComponent (), en cuyo caso, la configuración de su archivo de configuración será ignorada. El siguiente código es lo que estoy llamando desde mi constructor de clase de instalador, antes de InitializeComponent ():
No creo que leer el archivo de configuración directamente desde ConfigurationManager.AppSettings o algo similar funcione, ya que cuando se ejecuta el instalador, se ejecuta en el contexto de InstallUtil.exe, no en el .exe de su servicio. Es posible que pueda hacer algo con ConfigurationManager.OpenExeConfiguration, sin embargo, en mi caso, esto no funcionó porque estaba tratando de acceder a una sección de configuración personalizada que no estaba cargada.
fuente
Solo para mejorar la respuesta perfecta de @ chris.house.00 esto , puede considerar la siguiente función para leer desde la configuración de su aplicación:
fuente
Tuve una situación similar, en la que necesitaba tener un servicio anterior y un servicio actualizado que se ejecutaba en paralelo en el mismo servidor. (Fue más que un simple cambio de base de datos, también fueron cambios de código). Así que no podía ejecutar el mismo .exe dos veces. Necesitaba un nuevo .exe compilado con nuevas DLL pero del mismo proyecto. El simple hecho de cambiar el nombre del servicio y el nombre para mostrar del servicio no funcionó para mí, todavía recibí el "error del servicio ya existía" que creo que se debe a que estoy usando un Proyecto de implementación. Lo que finalmente funcionó para mí es que dentro de las Propiedades de mi proyecto de implementación hay una propiedad llamada "ProductCode", que es un Guid.
Después de eso, reconstruir el proyecto de instalación a un nuevo .exe o .msi instalado correctamente.
fuente
El enfoque más simple es basar el nombre del servicio en el nombre de la dll:
fuente