Deshalb haben wir einen Windows-Dienst erstellt, um Daten an unsere Client-Anwendung weiterzuleiten, und alles läuft hervorragend. Der Client hat eine unterhaltsame Konfigurationsanforderung erstellt, für die zwei Instanzen dieses Dienstes auf demselben Server ausgeführt und so konfiguriert werden müssen, dass sie auf separate Datenbanken verweisen.
Bisher war ich nicht in der Lage, dies zu erreichen, und ich hoffte, dass meine Kollegen im Stackoverflow möglicherweise einige Hinweise geben könnten, warum.
Aktuelles Setup:
Ich habe das Projekt eingerichtet, das den Windows-Dienst enthält. Wir nennen es ab sofort AppService und die Datei ProjectInstaller.cs, die benutzerdefinierte Installationsschritte ausführt, um den Dienstnamen basierend auf einem Schlüssel in der App.config wie folgt festzulegen ::
this.serviceInstaller1.ServiceName = Util.ServiceName;
this.serviceInstaller1.DisplayName = Util.ServiceName;
this.serviceProcessInstaller1.Account = System.ServiceProcess.ServiceAccount.LocalSystem;
In diesem Fall ist Util nur eine statische Klasse, die den Dienstnamen aus der Konfigurationsdatei lädt.
Von hier an habe ich zwei verschiedene Methoden ausprobiert, um beide Dienste zu installieren, und beide sind auf identische Weise fehlgeschlagen.
Die erste Möglichkeit bestand darin, einfach die erste Kopie des Dienstes zu installieren, das installierte Verzeichnis zu kopieren und umzubenennen und dann den folgenden Befehl auszuführen, nachdem die App-Konfiguration geändert wurde, um den gewünschten Dienstnamen zu ändern:
InstallUtil.exe /i AppService.exe
Als das nicht funktionierte, habe ich versucht, ein zweites Installationsprojekt zu erstellen, die Konfigurationsdatei bearbeitet und das zweite Installationsprogramm erstellt. Als ich das Installationsprogramm ausführte, funktionierte es einwandfrei, aber der Dienst wurde nicht in services.msc angezeigt, sodass ich den vorherigen Befehl für die zweite installierte Codebasis ausführte.
Beide Male habe ich die folgende Ausgabe von InstallUtil erhalten (nur relevante Teile):
Ausführen einer getätigten Installation.
Beginn der Installationsphase der Installation.
Installieren von Service App Service Two ... Service App Service Two wurde erfolgreich installiert. Erstellen des EventLog-Quell-App-Dienstes Zwei im Protokoll Anwendung ...
Während der Installationsphase ist eine Ausnahme aufgetreten. System.NullReferenceException: Objektreferenz nicht auf eine Instanz eines Objekts festgelegt.
Die Rollback-Phase der Installation beginnt.
Wiederherstellen des Ereignisprotokolls auf den vorherigen Status für Quell-App-Service Zwei. Service App Service Two wird aus dem System entfernt ... Service App Service Two wurde erfolgreich aus dem System entfernt.
Die Rollback-Phase wurde erfolgreich abgeschlossen.
Die getätigte Installation ist abgeschlossen. Die Installation ist fehlgeschlagen und das Rollback wurde durchgeführt.
Entschuldigung für den langwierigen Beitrag, wollte sicherstellen, dass es genügend relevante Informationen gibt. Das Stück, das mich bisher verblüfft hat, ist, dass es besagt, dass die Installation des Dienstes erfolgreich abgeschlossen wurde und dass die NullReferenceException erst ausgelöst wird, nachdem die EventLog-Quelle erstellt wurde. Wenn also jemand weiß, was ich falsch mache oder einen besseren Ansatz hat, wäre er sehr dankbar.
http://journalofasoftwaredev.wordpress.com/2008/07/16/multiple-instances-of-same-windows-service/
. Sie können Code in das Installationsprogramm einfügen, um den gewünschten Dienstnamen zu erhalten, wenn Sie installutil ausführen.Diese Lösung hat bei mir funktioniert.
quelle
[path to your exe]
muss voller Pfad sein und den Raum nachbinpath=
Sie können mehrere Versionen desselben Dienstes ausführen, indem Sie folgende Schritte ausführen:
1) Kopieren Sie die ausführbare Datei und die Konfiguration des Dienstes in einen eigenen Ordner.
2) Kopieren Sie Install.Exe in den ausführbaren Ordner des Dienstes (aus dem .net Framework-Ordner).
3) Erstellen Sie eine Konfigurationsdatei mit dem Namen Install.exe.config im ausführbaren Ordner des Dienstes mit den folgenden Inhalten (eindeutige Dienstnamen):
4) Erstellen Sie eine Batchdatei, um den Dienst mit den folgenden Inhalten zu installieren:
5) Erstellen Sie während Ihres Aufenthalts eine Batchdatei zum Deinstallieren
BEARBEITEN:
Wenn ich etwas verpasst habe, ist hier die ServiceInstaller-Klasse (nach Bedarf anpassen):
quelle
Alte Frage, ich weiß, aber ich hatte Glück mit der Option / servicename auf InstallUtil.exe. Ich sehe es jedoch nicht in der eingebauten Hilfe.
Ich bin mir nicht ganz sicher, wo ich das erste Mal darüber gelesen habe, aber ich habe es seitdem nicht mehr gesehen. YMMV.
quelle
An exception occurred during the Install phase. System.ComponentModel.Win32Exception: The specified service already exists
Eine weitere schnelle Möglichkeit, einen benutzerdefinierten Wert für
ServiceName
und anzugeben,DisplayName
ist die Verwendung voninstallutil
Befehlszeilenparametern.ProjectInstaller
Überschreiben Sie in Ihrer Klasse virtuelle MethodenInstall(IDictionary stateSaver)
undUninstall(IDictionary savedState)
Installieren Sie den Dienst,
installutil
indem Sie Ihren benutzerdefinierten Namen mithilfe des folgenden/servicename
Parameters hinzufügen :Beachten Sie, dass
/servicename
der Dienst mit den in ProjectInstaller properties / config angegebenen Werten für ServiceName und DisplayName installiert wird , wenn Sie dies nicht in der Befehlszeile angebenquelle
Ich hatte nicht viel Glück mit den oben genannten Methoden, als ich unsere automatisierte Bereitstellungssoftware zum häufigen Installieren / Deinstallieren von Windows-Diensten nebeneinander verwendete, aber ich kam schließlich auf Folgendes, mit dem ich einen Parameter übergeben konnte, um ein Suffix anzugeben auf den Dienstnamen in der Befehlszeile. Außerdem kann der Designer ordnungsgemäß funktionieren und kann bei Bedarf problemlos angepasst werden, um den gesamten Namen zu überschreiben.
In diesem Sinne kann ich Folgendes tun: Wenn ich den Dienst "Awesome Service" genannt habe, kann ich eine UAT-Version des Dienstes wie folgt installieren:
InstallUtil.exe /ServiceSuffix="UAT" MyService.exe
Dadurch wird der Dienst mit dem Namen "Awesome Service - UAT" erstellt. Wir haben dies verwendet, um DEVINT-, TESTING- und ACCEPTANCE-Versionen desselben Dienstes auszuführen, die nebeneinander auf einem einzelnen Computer ausgeführt werden. Jede Version verfügt über einen eigenen Satz von Dateien / Konfigurationen. Ich habe nicht versucht, mehrere Dienste zu installieren, die auf denselben Satz von Dateien verweisen.
HINWEIS: Sie müssen denselben
/ServiceSuffix
Parameter zum Deinstallieren des Dienstes verwenden, damit Sie zur Deinstallation Folgendes ausführen können:InstallUtil.exe /u /ServiceSuffix="UAT" MyService.exe
quelle
/ServiceSuffix="UAT"
wird vom Installationsprogramm verwendet, um das Suffix für den Dienst festzulegen. In meinem Beispiel ist der übergebene WertUAT
. In meinem Szenario wollte ich dem vorhandenen Namen des Dienstes nur ein Suffix hinzufügen, aber es gibt keinen Grund, warum Sie dies nicht anpassen könnten, um den Namen vollständig durch den übergebenen Wert zu ersetzen.Um dies zu erreichen, habe ich den Dienstnamen und den Anzeigenamen in einer app.config für meinen Dienst gespeichert. Dann lade ich in meiner Installationsklasse die Datei app.config als XmlDocument und verwende xpath, um die Werte abzurufen und auf ServiceInstaller.ServiceName und ServiceInstaller.DisplayName anzuwenden, bevor ich InitializeComponent () aufrufe. Dies setzt voraus, dass Sie diese Eigenschaften nicht bereits in InitializeComponent () festlegen. In diesem Fall werden die Einstellungen aus Ihrer Konfigurationsdatei ignoriert. Der folgende Code wird von meinem Installer-Klassenkonstruktor vor InitializeComponent () aufgerufen:
Ich glaube nicht, dass das Lesen der Konfigurationsdatei direkt aus ConfigurationManager.AppSettings oder ähnlichem funktioniert, wenn das Installationsprogramm ausgeführt wird. Es wird im Kontext von InstallUtil.exe ausgeführt, nicht in der EXE-Datei Ihres Dienstes. Möglicherweise können Sie mit ConfigurationManager.OpenExeConfiguration etwas tun. In meinem Fall funktionierte dies jedoch nicht, da ich versuchte, zu einem benutzerdefinierten Konfigurationsabschnitt zu gelangen, der nicht geladen wurde.
quelle
Nur um perfekte Antwort von @ chris.house.00 zu verbessern diese , können Sie folgende Funktion betrachten von Ihren App - Einstellungen zu lesen:
quelle
Ich hatte eine ähnliche Situation, in der ich einen vorherigen Dienst und einen aktualisierten Dienst benötigte, der nebeneinander auf demselben Server ausgeführt wurde. (Es war mehr als nur eine Datenbankänderung, es waren auch Codeänderungen). Ich konnte also nicht zweimal dieselbe EXE-Datei ausführen. Ich brauchte eine neue EXE-Datei, die mit neuen DLLs kompiliert wurde, aber aus demselben Projekt stammt. Nur das Ändern des Dienstnamens und des Anzeigenamens des Dienstes hat bei mir nicht funktioniert. Ich habe immer noch den Fehler "Dienst bereits vorhanden" erhalten, der meiner Meinung nach darauf zurückzuführen ist, dass ich ein Bereitstellungsprojekt verwende. Was letztendlich für mich funktioniert hat, ist, dass es in meinen Deployment Project-Eigenschaften eine Eigenschaft namens "ProductCode" gibt, die eine Richtlinie ist.
Danach wird das Setup-Projekt auf eine neue .exe oder .msi neu installiert, die erfolgreich installiert wurde.
quelle
Der einfachste Ansatz besteht darin, den Dienstnamen auf dem DLL-Namen zu basieren:
quelle