Dlatego stworzyliśmy usługę Windows do dostarczania danych do naszej aplikacji klienckiej i wszystko idzie świetnie. Klient wymyślił zabawne żądanie konfiguracji, które wymaga dwóch wystąpień tej usługi działających na tym samym serwerze i skonfigurowanych do wskazywania oddzielnych baz danych.
Do tej pory nie byłem w stanie tego zrobić i miałem nadzieję, że moi koledzy z stackoverflow mogą dać kilka wskazówek, dlaczego.
Obecne ustawienia:
Skonfigurowałem projekt, który zawiera usługę systemu Windows, od teraz będziemy go nazywać AppService i plik ProjectInstaller.cs, który obsługuje niestandardowe kroki instalacji, aby ustawić nazwę usługi na podstawie klucza w pliku App.config :
this.serviceInstaller1.ServiceName = Util.ServiceName;
this.serviceInstaller1.DisplayName = Util.ServiceName;
this.serviceProcessInstaller1.Account = System.ServiceProcess.ServiceAccount.LocalSystem;
W tym przypadku Util jest po prostu klasą statyczną, która ładuje nazwę usługi z pliku konfiguracyjnego.
Odtąd próbowałem zainstalować obie usługi na dwa różne sposoby i obie zakończyły się niepowodzeniem w identyczny sposób.
Pierwszym sposobem było po prostu zainstalowanie pierwszej kopii usługi, skopiowanie zainstalowanego katalogu i zmiana jego nazwy, a następnie uruchomienie następującego polecenia po zmodyfikowaniu konfiguracji aplikacji, aby zmienić żądaną nazwę usługi:
InstallUtil.exe /i AppService.exe
Kiedy to nie zadziałało, próbowałem stworzyć drugi projekt instalatora, wyedytowałem plik konfiguracyjny i zbudowałem drugi instalator. Kiedy uruchomiłem instalator, działało dobrze, ale usługa nie pojawiła się w services.msc, więc uruchomiłem poprzednie polecenie dla drugiej zainstalowanej bazy kodu.
Za każdym razem otrzymałem następujące dane wyjściowe z InstallUtil (tylko odpowiednie części):
Uruchamianie przeprowadzonej instalacji.
Rozpoczynanie fazy instalacji instalacji.
Instalowanie usługi App Service Two ... Usługa App Service Two została pomyślnie zainstalowana. Tworzenie źródła EventLog App Service Two w dzienniku aplikacji ...
Wystąpił wyjątek podczas fazy instalacji. System.NullReferenceException: odwołanie do obiektu nie jest ustawione na wystąpienie obiektu.
Rozpoczyna się faza wycofywania instalacji.
Przywracanie dziennika zdarzeń do poprzedniego stanu dla źródłowej usługi App Service Two. Usługa Service App Service 2 jest usuwana z systemu ... Service App Service 2 została pomyślnie usunięta z systemu.
Faza wycofywania została zakończona pomyślnie.
Transakcja instalacji została zakończona. Instalacja nie powiodła się i przywrócenie zostało wykonane.
Przepraszamy za rozwlekły post, chciałem się upewnić, że jest wystarczająco dużo istotnych informacji. Element, który do tej pory mnie zaskoczył, to stwierdzenie, że instalacja usługi zakończyła się pomyślnie i dopiero po utworzeniu źródła EventLog wydaje się, że NullReferenceException zostaje wyrzucony. Więc jeśli ktoś wie, co robię źle lub ma lepsze podejście, będzie to bardzo wdzięczne.
http://journalofasoftwaredev.wordpress.com/2008/07/16/multiple-instances-of-same-windows-service/
. Możesz wstawić kod do instalatora, aby uzyskać żądaną nazwę usługi po uruchomieniu installutil.To rozwiązanie zadziałało dla mnie.
źródło
[path to your exe]
musi być pełną ścieżką i nie zapomnij o spacji pobinpath=
Możesz uruchomić wiele wersji tej samej usługi, wykonując następujące czynności:
1) Skopiuj plik wykonywalny usługi i konfigurację do własnego folderu.
2) Skopiuj plik Install.Exe do folderu wykonywalnego usługi (z folderu platformy .net)
3) Utwórz plik konfiguracyjny o nazwie Install.exe.config w folderze wykonywalnym usługi o następującej zawartości (unikalne nazwy usług):
4) Utwórz plik wsadowy, aby zainstalować usługę o następującej zawartości:
5) Będąc tam, utwórz plik wsadowy dezinstalacji
EDYTOWAĆ:
Pamiętaj, że jeśli coś przegapiłem, oto klasa ServiceInstaller (dostosuj zgodnie z wymaganiami):
źródło
Stare pytanie, wiem, ale miałem szczęście, używając opcji / nazwa usługi w programie InstallUtil.exe. Nie widzę tego jednak we wbudowanej pomocy.
Nie jestem do końca pewien, gdzie po raz pierwszy o tym przeczytałem, ale od tamtej pory tego nie widziałem. YMMV.
źródło
An exception occurred during the Install phase. System.ComponentModel.Win32Exception: The specified service already exists
Innym szybkim sposobem określenia wartości niestandardowej dla
ServiceName
iDisplayName
jest użycieinstallutil
parametrów wiersza polecenia.W Twojej
ProjectInstaller
klasie zastąp metody wirtualneInstall(IDictionary stateSaver)
iUninstall(IDictionary savedState)
Zainstaluj usługę,
installutil
dodając własną nazwę za pomocą/servicename
parametru:Należy pamiętać, że jeśli nie określisz
/servicename
w wierszu poleceń, usługa zostanie zainstalowana z wartościami ServiceName i DisplayName określonymi we właściwościach ProjectInstaller / configźródło
Nie miałem szczęścia z powyższymi metodami, gdy korzystałem z naszego oprogramowania do automatycznego wdrażania do częstego instalowania / odinstalowywania usług systemu Windows obok siebie, ale w końcu wymyśliłem następujące, które pozwala mi przekazać parametr określający sufiks do nazwy usługi w wierszu poleceń. Pozwala również projektantowi na prawidłowe funkcjonowanie i można go łatwo dostosować, aby w razie potrzeby zastąpić całą nazwę.
Mając to na uwadze, mogę wykonać następujące czynności: Jeśli zadzwoniłem do usługi „Awesome Service”, mogę zainstalować wersję usługi UAT w następujący sposób:
InstallUtil.exe /ServiceSuffix="UAT" MyService.exe
Spowoduje to utworzenie usługi o nazwie „Awesome Service - UAT”. Użyliśmy tego do uruchomienia wersji DEVINT, TESTING i ACCEPTANCE tej samej usługi działającej równolegle na jednym komputerze. Każda wersja ma swój własny zestaw plików / konfiguracji - nie próbowałem instalować wielu usług wskazujących na ten sam zestaw plików.
UWAGA: musisz użyć tego samego
/ServiceSuffix
parametru, aby odinstalować usługę, więc aby odinstalować, wykonaj następujące czynności:InstallUtil.exe /u /ServiceSuffix="UAT" MyService.exe
źródło
/ServiceSuffix="UAT"
jest używana przez instalator do ustawiania sufiksu w usłudze. W moim przykładzie przekazana wartość toUAT
. W moim scenariuszu chciałem po prostu dodać sufiks do istniejącej nazwy usługi, ale nie ma powodu, dla którego nie mógłbyś dostosować tego, aby całkowicie zastąpić nazwę przekazaną wartością.Aby to zadziałało, zapisałem nazwę usługi i nazwę wyświetlaną w pliku app.config dla mojej usługi. Następnie w mojej klasie instalatora ładuję plik app.config jako XmlDocument i używam xpath, aby pobrać wartości i zastosować je do ServiceInstaller.ServiceName i ServiceInstaller.DisplayName, przed wywołaniem InitializeComponent (). Zakłada się, że nie ustawiłeś jeszcze tych właściwości w InitializeComponent (), w takim przypadku ustawienia z pliku konfiguracyjnego zostaną zignorowane. Poniższy kod jest tym, co wywołuję z mojego konstruktora klasy Instalatora, przed InitializeComponent ():
Nie wierzę, że czytanie pliku konfiguracyjnego bezpośrednio z ConfigurationManager.AppSettings lub czegoś podobnego będzie działało tak, jak po uruchomieniu instalatora, jest uruchamiany w kontekście InstallUtil.exe, a nie .exe Twojej usługi. Możesz być w stanie zrobić coś z ConfigurationManager.OpenExeConfiguration, jednak w moim przypadku to nie zadziałało, ponieważ próbowałem uzyskać niestandardową sekcję konfiguracji, która nie została załadowana.
źródło
Wystarczy, aby poprawić doskonałą odpowiedź @ chris.house.00 tego , można rozważyć następujące funkcje odczytu z ustawieniami aplikacji:
źródło
Miałem podobną sytuację, w której potrzebowałem poprzedniej usługi i zaktualizowanej usługi działającej obok siebie na tym samym serwerze. (To było coś więcej niż tylko zmiana bazy danych, to także zmiany kodu). Nie mogłem więc po prostu dwukrotnie uruchomić tego samego pliku .exe. Potrzebowałem nowego pliku .exe, który został skompilowany z nowymi bibliotekami DLL, ale z tego samego projektu. Sama zmiana nazwy usługi i nazwy wyświetlanej usługi nie zadziałała. Nadal otrzymuję komunikat „usługa już istnieje”, co moim zdaniem wynika z tego, że używam projektu wdrożeniowego. To, co w końcu zadziałało, to w moich właściwościach projektu wdrożeniowego znajduje się właściwość o nazwie „ProductCode”, która jest Guid.
Następnie pomyślnie odbuduj projekt instalacji do nowego zainstalowanego pliku .exe lub .msi.
źródło
Najprostszym podejściem jest oparcie nazwy usługi na nazwie biblioteki DLL:
źródło