Nous avons donc produit un service Windows pour fournir des données à notre application client et tout se passe bien. Le client a présenté une demande de configuration amusante qui nécessite deux instances de ce service s'exécutant sur le même serveur et configurées pour pointer vers des bases de données distinctes.
Jusqu'à présent, je n'ai pas été en mesure de faire en sorte que cela se produise et j'espérais que mes collègues membres de stackoverflow pourraient être en mesure de vous expliquer pourquoi.
Configuration actuelle:
J'ai configuré le projet qui contient le service Windows, nous l'appellerons désormais AppService, et le fichier ProjectInstaller.cs qui gère les étapes d'installation personnalisées pour définir le nom du service en fonction d'une clé dans App.config comme suit :
this.serviceInstaller1.ServiceName = Util.ServiceName;
this.serviceInstaller1.DisplayName = Util.ServiceName;
this.serviceProcessInstaller1.Account = System.ServiceProcess.ServiceAccount.LocalSystem;
Dans ce cas, Util est juste une classe statique qui charge le nom du service à partir du fichier de configuration.
À partir de maintenant, j'ai essayé deux façons différentes d'installer les deux services et les deux ont échoué de la même manière.
La première méthode consistait simplement à installer la première copie du service, à copier le répertoire installé et à le renommer, puis à exécuter la commande suivante après avoir modifié la configuration de l'application pour changer le nom du service souhaité:
InstallUtil.exe /i AppService.exe
Lorsque cela n'a pas fonctionné, j'ai essayé de créer un deuxième projet d'installation, modifié le fichier de configuration et construit le deuxième programme d'installation. Lorsque j'ai exécuté le programme d'installation, cela fonctionnait bien mais le service ne s'affichait pas dans services.msc, j'ai donc exécuté la commande précédente sur la deuxième base de code installée.
Les deux fois, j'ai reçu la sortie suivante d'InstallUtil (parties pertinentes uniquement):
Exécution d'une installation traitée.
Début de la phase d'installation de l'installation.
Installation du service App Service Two ... Le service App Service Two a été installé avec succès. Création de l'application EventLog source App Service Two dans l'application de journal ...
Une exception s'est produite lors de la phase d'installation. System.NullReferenceException: La référence d'objet n'est pas définie sur une instance d'un objet.
La phase de restauration de l'installation commence.
Restauration du journal des événements à l'état précédent pour App Service Two source. Service App Service Two est en cours de suppression du système ... Service App Service Two a été supprimé du système avec succès.
La phase de restauration s'est terminée avec succès.
L'installation traitée est terminée. L'installation a échoué et la restauration a été effectuée.
Désolé pour le long post, je voulais m'assurer qu'il y avait suffisamment d'informations pertinentes. L'élément qui m'a jusqu'à présent perplexe est qu'il indique que l'installation du service se termine avec succès et que ce n'est qu'après avoir créé la source EventLog que l'exception NullReferenceException semble être lancée. Donc, si quelqu'un sait ce que je fais de mal ou a une meilleure approche, ce serait très apprécié.
http://journalofasoftwaredev.wordpress.com/2008/07/16/multiple-instances-of-same-windows-service/
. Vous pouvez insérer du code dans le programme d'installation pour obtenir le nom de service souhaité lorsque vous exécutez installutil.Cette solution a fonctionné pour moi.
la source
[path to your exe]
doit être chemin complet et n'oubliez pas l'espace aprèsbinpath=
Vous pouvez exécuter plusieurs versions du même service en procédant comme suit:
1) Copiez l'exécutable et la configuration du service dans son propre dossier.
2) Copiez Install.Exe dans le dossier exécutable du service (à partir du dossier .net framework)
3) Créez un fichier de configuration appelé Install.exe.config dans le dossier exécutable du service avec le contenu suivant (noms de service uniques):
4) Créez un fichier de commandes pour installer le service avec le contenu suivant:
5) Pendant que vous y êtes, créez un fichier batch de désinstallation
ÉDITER:
Notez que si j'ai manqué quelque chose, voici la classe ServiceInstaller (ajustez si nécessaire):
la source
Ancienne question, je sais, mais j'ai eu de la chance en utilisant l'option / servicename sur InstallUtil.exe. Cependant, je ne le vois pas répertorié dans l'aide intégrée.
Je ne sais pas exactement où j'ai lu pour la première fois à ce sujet, mais je ne l'ai pas vu depuis. YMMV.
la source
An exception occurred during the Install phase. System.ComponentModel.Win32Exception: The specified service already exists
Un autre moyen rapide de spécifier une valeur personnalisée pour
ServiceName
etDisplayName
consiste à utiliser desinstallutil
paramètres de ligne de commande.Dans votre
ProjectInstaller
classe, remplacez les méthodes virtuellesInstall(IDictionary stateSaver)
etUninstall(IDictionary savedState)
Installez le service en
installutil
ajoutant votre nom personnalisé à l'aide du/servicename
paramètre:Veuillez noter que si vous ne spécifiez pas
/servicename
dans la ligne de commande, le service sera installé avec les valeurs ServiceName et DisplayName spécifiées dans ProjectInstaller properties / configla source
Je n'ai pas eu beaucoup de chance avec les méthodes ci-dessus lors de l'utilisation de notre logiciel de déploiement automatisé pour installer / désinstaller fréquemment des services Windows côte à côte, mais j'ai finalement proposé ce qui suit qui me permet de passer un paramètre pour spécifier un suffixe au nom du service sur la ligne de commande. Il permet également au concepteur de fonctionner correctement et peut facilement être adapté pour remplacer le nom entier si nécessaire.
Dans cet esprit, je peux faire ce qui suit: Si j'ai appelé le service "Awesome Service", je peux installer une version UAT du service comme suit:
InstallUtil.exe /ServiceSuffix="UAT" MyService.exe
Cela créera le service avec le nom "Awesome Service - UAT". Nous l'avons utilisé pour exécuter les versions DEVINT, TESTING et ACCEPTANCE du même service côte à côte sur une seule machine. Chaque version a son propre ensemble de fichiers / configurations - je n'ai pas essayé cela pour installer plusieurs services pointant vers le même ensemble de fichiers.
REMARQUE: vous devez utiliser le même
/ServiceSuffix
paramètre pour désinstaller le service, vous devez donc exécuter ce qui suit pour désinstaller:InstallUtil.exe /u /ServiceSuffix="UAT" MyService.exe
la source
/ServiceSuffix="UAT"
est utilisée par le programme d'installation pour définir le suffixe sur le service. Dans mon exemple, la valeur transmise estUAT
. Dans mon scénario, je voulais juste ajouter un suffixe au nom existant du service, mais il n'y a aucune raison pour que vous ne puissiez pas l'adapter pour remplacer entièrement le nom par la valeur transmise.Ce que j'ai fait pour que cela fonctionne, c'est de stocker le nom du service et le nom d'affichage dans un app.config pour mon service. Ensuite, dans ma classe d'installation, je charge app.config en tant que XmlDocument et utilise xpath pour obtenir les valeurs et les appliquer à ServiceInstaller.ServiceName et ServiceInstaller.DisplayName, avant d'appeler InitializeComponent (). Cela suppose que vous ne définissez pas déjà ces propriétés dans InitializeComponent (), auquel cas les paramètres de votre fichier de configuration seront ignorés. Le code suivant est ce que j'appelle de mon constructeur de classe d'installation, avant InitializeComponent ():
Je ne crois pas que la lecture du fichier de configuration directement à partir de ConfigurationManager.AppSettings ou quelque chose de similaire fonctionnera car lorsque le programme d'installation s'exécute, il est exécuté dans le contexte d'InstallUtil.exe, pas .exe de votre service. Vous pourrez peut-être faire quelque chose avec ConfigurationManager.OpenExeConfiguration, mais dans mon cas, cela n'a pas fonctionné car j'essayais d'accéder à une section de configuration personnalisée qui n'était pas chargée.
la source
Juste pour améliorer la réponse parfaite de @ chris.house.00 ceci , vous pouvez envisager la fonction suivante pour lire les paramètres de votre application:
la source
J'ai eu une situation similaire, où je devais avoir un service précédent et un service mis à jour fonctionnant côte à côte sur le même serveur. (C'était plus qu'un simple changement de base de données, c'était aussi des changements de code). Je ne pouvais donc pas exécuter le même .exe deux fois. J'avais besoin d'un nouveau .exe compilé avec de nouvelles DLL mais à partir du même projet. Le simple fait de changer le nom du service et le nom d'affichage du service ne fonctionnait pas pour moi, je recevais quand même l'erreur "le service existait déjà", ce qui, je crois, est dû au fait que j'utilise un projet de déploiement. Ce qui a finalement fonctionné pour moi, c'est dans les propriétés de mon projet de déploiement, il y a une propriété appelée "ProductCode" qui est un Guid.
Après cela, la reconstruction du projet d'installation vers un nouveau .exe ou .msi installé avec succès.
la source
L'approche la plus simple est basée le nom du service sur le nom de la DLL:
la source