Не удалось установить и запустить службы Windows в установщике WiX
Я создаю пакет MSI для установки и запуска служб Windows с помощью WiX v3.8. Код выглядит следующим образом:
<Component Id="INSTALLAPSSERVICE" Guid="991D5F82-0E77-4FE3-B1D8-4C941B84C7CD" Win64="yes">
<File Id="ApsService.exe"
Name="ApsService.exe"
Source="Resource\ApsService.exe"
KeyPath="yes"
Vital="yes"
DiskId="1"></File>
<ServiceInstall Id="ApsServiceInstaller"
Name="ApsService"
DisplayName="ApsService"
Type="ownProcess"
Start="auto"
ErrorControl="normal"
Description="A monitor service for windows application."
Account="[SERVICEACCOUNT]"
Password="[SERVICEPASSWORD]"
Vital="yes"
Interactive="no"></ServiceInstall>
<ServiceControl Id="StartService"
Start="install"
Stop="both"
Remove="uninstall"
Name="ApsService"
Wait="yes"/>
</Component>
Но установка завершается с ошибками в журнале:
Executing op: ServiceControl(,Name=ApsService,Action=1,Wait=1,)
StartServices: Service: ApsService
Error 1920. Service 'ApsService' (ApsService) failed to start. Verify that you have sufficient privileges to start system services.
MSI (s) (F0:D0) [15:57:28:630]: I/O on thread 3676 could not be cancelled. Error: 1168
MSI (s) (F0:D0) [15:57:28:630]: I/O on thread 1888 could not be cancelled. Error: 1168
MSI (s) (F0:D0) [15:57:28:630]: I/O on thread 1764 could not be cancelled. Error: 1168
MSI (s) (F0:D0) [15:57:28:630]: I/O on thread 3504 could not be cancelled. Error: 1168
MSI (s) (F0:D0) [15:57:28:630]: I/O on thread 2100 could not be cancelled. Error: 1168
MSI (s) (F0:D0) [15:57:28:630]: I/O on thread 2752 could not be cancelled. Error: 1168
MSI (s) (F0:D0) [15:57:28:630]: I/O on thread 3672 could not be cancelled. Error: 1168
MSI (s) (F0:D0) [15:57:28:630]: I/O on thread 3876 could not be cancelled. Error: 1168
MSI (s) (F0:D0) [15:57:28:630]: I/O on thread 1400 could not be cancelled. Error: 1168
MSI (s) (F0:C0) [15:57:28:630]: Product: WinApsSetup64 -- Error 1920. Service 'ApsService' (ApsService) failed to start. Verify that you have sufficient privileges to start system services.
Как я могу исправить ошибки?
Ответы
Ответ 1
Сообщение об ошибке, которое вы получаете, является общим сообщением, которое установщик Windows отправляет, когда ему не удается запустить службу во время установки. Почти всегда проблема заключается в том, что службе не хватает зависимости или иначе не полностью сконфигурирована при запуске. Чтобы отладить корневую проблему, попробуйте:
- Установите пакет MSI.
- Когда появляется диалоговое окно с ошибкой, указывающее на то, что не удалось запустить службу * не отключайте диалог.
- Запустите services.msc или используйте sc.exe из командной строки, чтобы попытаться запустить службу. Установщик Windows должен был настроить достаточно службы, чтобы иметь возможность отлаживать глубже, почему это не удалось.
- При необходимости отлаживайтесь в свой служебный исполняемый файл напрямую, чтобы понять, почему он не может быть запущен.
Если это служба, написанная в управляемом коде, убедитесь, что она не зависит от файлов, размещенных в GAC. Файлы не находятся в GAC, пока очень, очень поздно в процессе установки. Если вы должны использовать файлы в GAC, вы не сможете использовать встроенный элемент ServiceControl
и должны будете написать настраиваемое действие для запуска после InstallFinalize
. Обратите внимание, что после InstallFinalize
пользовательское действие не будет повышаться, поэтому ваша служба должна будет поддерживать запуск без добавления пользователей. Опять же, я рекомендую не в зависимости от ПКК.
Удачи отладки вашей службы!
Ответ 2
Учетная запись ServiceInstall запутана в примере OP, но эта ошибка может произойти, если вы забыли полностью квалифицировать учетную запись:
<ServiceInstall ... Account="NT AUTHORITY\LocalService" />
Ваш установщик потерпит неудачу, если вы укажете только имя пользователя (без полномочий NT), например:
<ServiceInstall ... Account="LocalService" />
Ответ 3
Не забудьте добавить права "Вход в систему" на [SERVICEACCOUNT],
Чтобы добавить право на учетную запись на вашем локальном компьютере, войдите в систему как услугу
1) Откройте локальную политику безопасности.
2) В дереве консоли дважды щелкните Локальные политики, а затем нажмите Назначения прав пользователя.
3) В области сведений дважды щелкните Зарегистрируйтесь как услугу.
4) Нажмите Добавить пользователя или группу, а затем добавьте соответствующую учетную запись в список учетных записей, которые имеют право Вход в систему как.
От: http://technet.microsoft.com/en-us/library/cc739424%28v=ws.10%29.aspx.
Ответ 4
При отладке проблемы с запуском службы я всегда использую простой оператор if(), который проверяет наличие определенного файла в каталоге установки. Когда служба выходит из строя, я открываю командную строку (перед тем, как отклонить диалог, указывающий на сбой) и использую "echo > thefile" для создания файла, который я ищу в if(). Объектом if() является вызов Debugger.Launch().
Теперь я могу отменить диалог и перезапустить установщик, и на этот раз он запустит отладчик, и я увижу, что произойдет. Я стараюсь использовать статический класс init в качестве момента запуска отладчика, но вы можете попытаться сделать это в "OnStart()", но если есть проблемы с загрузкой/привязкой, вы, вероятно, не дойдете до этого момента, прежде чем он умрет, Принимая во внимание статический класс init, вы всегда будете говорить о том, что вам нужно решать в качестве зависимостей.
Ответ 5
Итак, я получил эту ошибку сегодня, потому что у моего сервиса были зависимости, которые должны были быть GACed перед запуском службы. Как оказалось, зависимости GACed являются последними установщиком, и на самом деле нет хорошего способа обойти это без создания какого-либо установщика bootstraper/multipart.
Однако я нашел следующее решение: развернуть сборки как на GAC, так и установить их в том же каталоге, что и служба. Таким образом, служба сможет найти библиотеки DLL при запуске в каталоге файлов программ, и они будут GACed (что было требованием по другим причинам).
Для этого мне пришлось создать две отдельные группы компонентов и "dummy" Directory:
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLDIR" Name="NameOfProgram" />
<Directory Id="GacDlls" Name="libs" />
</Directory>
</Directory>
Затем я создаю две группы компонентов: одну, у которой есть exe и все библиотеки, а вторая с теми же библиотеками с атрибутом Assembly, установленным на ".net":
<ComponentGroup Id="ServiceLibs" Directory="GACDlls">
<Component Id="log4netGAC"
Guid="a23099ac-5880-4b6e-af3f-fa7cef113226">
<File Id="log4net.dllGAC"
Name="log4net.dll"
Source="..\ProjectDir\bin\$(var.Configuration)\log4net.dll"
KeyPath="yes"
Vital="yes"
DiskId="1"
Assembly=".net"
/>
</Component>
</ComponentGroup>
<ComponentGroup Id="ProductComponents" Directory="INSTALLDIR">
<Component Id="log4net"
Guid="463e05db-e248-44d7-bbde-467358b7310f">
<!-- normally we'd want to GAC this (Assembly=".net"), but that would prevent us from starting the service up during install so we'll just drop it in the program folder -->
<File Id="log4net.dll"
Name="log4net.dll"
Source="..\ProjectName\bin\$(var.Configuration)\log4net.dll"
KeyPath="yes"
Vital="yes"
DiskId="1"
/>
</Component>
... other components ...
</ComponentGroup>
И теперь это работает!