Итак, мы создали службу Windows для передачи данных нашему клиентскому приложению, и все идет отлично. Клиент придумал забавный запрос конфигурации, который требует, чтобы два экземпляра этой службы работали на одном сервере и были настроены так, чтобы указывать на разные базы данных.
До сих пор я не мог этого добиться и надеялся, что мои коллеги-участники stackoverflow смогут дать некоторые подсказки, почему.
Текущая настройка:
Я настроил проект, содержащий службу Windows, с этого момента мы будем называть его AppService, и файл ProjectInstaller.cs, который обрабатывает пользовательские шаги установки, чтобы задать имя службы на основе ключа в App.config, например, так :
this.serviceInstaller1.ServiceName = Util.ServiceName;
this.serviceInstaller1.DisplayName = Util.ServiceName;
this.serviceProcessInstaller1.Account = System.ServiceProcess.ServiceAccount.LocalSystem;
В этом случае Util - это просто статический класс, который загружает имя службы из файла конфигурации.
С этого момента я пробовал два разных способа установить обе службы, и оба потерпели неудачу одинаково.
Первый способ заключался в том, чтобы просто установить первую копию службы, скопировать установленный каталог и переименовать его, а затем выполнить следующую команду после изменения конфигурации приложения, чтобы изменить желаемое имя службы:
InstallUtil.exe /i AppService.exe
Когда это не сработало, я попытался создать второй проект установщика, отредактировал файл конфигурации и построил второй установщик. Когда я запустил установщик, он работал нормально, но служба не отображалась в services.msc, поэтому я выполнил предыдущую команду для второй установленной базы кода.
Оба раза я получил следующий вывод от InstallUtil (только соответствующие части):
Запуск транзакционной установки.
Начало этапа установки.
Установка службы приложений два ... Служба приложений службы два успешно установлена. Создание службы приложений источника журнала событий Два в приложении журнала ...
Исключение произошло на этапе установки. System.NullReferenceException: ссылка на объект не установлена на экземпляр объекта.
Начинается этап отката установки.
Восстановление журнала событий до предыдущего состояния для исходной службы приложений 2. Служба приложений-служб 2 удаляется из системы ... Служба приложений-служб 2 была успешно удалена из системы.
Этап отката успешно завершен.
Транзакционная установка завершена. Установка не удалась, откат выполнен.
Извините за многословный пост, хотел убедиться, что в нем достаточно актуальной информации. Кусок, который до сих пор меня озадачил, заключается в том, что в нем говорится, что установка службы завершается успешно, и только после того, как она перейдет к созданию источника EventLog, который, похоже, выбрасывается. Так что, если кто-нибудь знает, что я делаю не так или у меня есть лучший подход, я был бы очень признателен.
http://journalofasoftwaredev.wordpress.com/2008/07/16/multiple-instances-of-same-windows-service/
. Вы можете вставить код в программу установки, чтобы получить нужное имя службы при запуске installutil.Это решение сработало для меня.
источник
[path to your exe]
должен быть полный путь и не забывайте пробел послеbinpath=
Вы можете запустить несколько версий одной и той же службы, выполнив следующие действия:
1) Скопируйте исполняемый файл и конфигурацию службы в отдельную папку.
2) Скопируйте Install.Exe в папку исполняемых файлов службы (из папки .NET framework)
3) Создайте файл конфигурации с именем Install.exe.config в папке исполняемых файлов службы со следующим содержимым (уникальные имена служб):
4) Создайте командный файл для установки службы со следующим содержимым:
5) Пока вы там, создайте командный файл удаления
РЕДАКТИРОВАТЬ:
Обратите внимание: если я что-то пропустил, вот класс ServiceInstaller (при необходимости отрегулируйте):
источник
Старый вопрос, я знаю, но мне повезло с использованием параметра / servicename в InstallUtil.exe. Однако я не вижу этого во встроенной справке.
Я не совсем уверен, где впервые прочитал об этом, но с тех пор не видел. YMMV.
источник
An exception occurred during the Install phase. System.ComponentModel.Win32Exception: The specified service already exists
Еще один быстрый способ указать настраиваемое значение для
ServiceName
иDisplayName
- использоватьinstallutil
параметры командной строки.В вашем
ProjectInstaller
классе переопределите виртуальные методыInstall(IDictionary stateSaver)
иUninstall(IDictionary savedState)
Установите сервис,
installutil
добавив свое собственное имя с помощью/servicename
параметра:Обратите внимание, что если вы не укажете
/servicename
в командной строке, служба будет установлена со значениями ServiceName и DisplayName, указанными в свойствах / config ProjectInstaller.источник
Мне не очень повезло с вышеуказанными методами при использовании нашего программного обеспечения для автоматического развертывания для частой установки / удаления параллельных служб Windows, но в конечном итоге я придумал следующее, которое позволяет мне передать параметр для указания суффикса к имени службы в командной строке. Это также позволяет конструктору работать правильно и может быть легко адаптировано для переопределения всего имени, если это необходимо.
Имея это в виду, я могу сделать следующее: если я назвал службу "Awesome Service", я могу установить версию службы UAT следующим образом:
InstallUtil.exe /ServiceSuffix="UAT" MyService.exe
Это создаст сервис с названием «Awesome Service - UAT». Мы использовали это для запуска версий DEVINT, TESTING и ACCEPTANCE одной и той же службы, работающих параллельно на одной машине. Каждая версия имеет свой собственный набор файлов / конфигураций - я не пробовал устанавливать несколько служб, указывающих на один и тот же набор файлов.
ПРИМЕЧАНИЕ: вы должны использовать тот же
/ServiceSuffix
параметр для удаления службы, поэтому для удаления вы должны выполнить следующее:InstallUtil.exe /u /ServiceSuffix="UAT" MyService.exe
источник
/ServiceSuffix="UAT"
используется установщиком для установки суффикса службы. В моем примере передано значениеUAT
. В моем сценарии я просто хотел добавить суффикс к существующему имени службы, но нет никаких причин, по которым вы не могли бы адаптировать это, чтобы полностью заменить имя переданным значением.Для выполнения этой работы я сохранил имя службы и отображаемое имя в app.config для моей службы. Затем в своем классе установщика я загружаю app.config как XmlDocument и использую xpath, чтобы получить значения и применить их к ServiceInstaller.ServiceName и ServiceInstaller.DisplayName перед вызовом InitializeComponent (). Предполагается, что вы еще не установили эти свойства в InitializeComponent (), и в этом случае настройки из вашего файла конфигурации будут проигнорированы. Следующий код - это то, что я вызываю из своего конструктора класса установщика перед InitializeComponent ():
Я не верю, что чтение файла конфигурации непосредственно из ConfigurationManager.AppSettings или что-то подобное будет работать, поскольку при запуске установщика он запускается в контексте InstallUtil.exe, а не в .exe вашей службы. Возможно, вы сможете что-то сделать с ConfigurationManager.OpenExeConfiguration, однако в моем случае это не сработало, поскольку я пытался получить доступ к настраиваемому разделу конфигурации, который не был загружен.
источник
Чтобы улучшить идеальный ответ @ chris.house.00 this , вы можете рассмотреть следующую функцию для чтения из настроек вашего приложения:
источник
У меня была аналогичная ситуация, когда мне нужно было иметь предыдущую службу и обновленную службу, работающую бок о бок на одном сервере. (Это было больше, чем просто изменение базы данных, это были также изменения кода). Поэтому я не мог просто запустить один и тот же .exe дважды. Мне нужен был новый .exe, который был скомпилирован с новыми DLL, но из того же проекта. Простое изменение имени службы и отображаемого имени службы у меня не сработало, я все еще получал «ошибка службы уже существует», которая, как мне кажется, связана с тем, что я использую проект развертывания. Что, наконец, сработало для меня, так это в моих свойствах проекта развертывания есть свойство под названием «ProductCode», которое является Guid.
После этого перестройка проекта установки на новый .exe или .msi успешно установлена.
источник
Самый простой подход основан на названии сервиса на имени dll:
источник