Wix: служба Windows иногда удаляется при обновлении
Мы устанавливаем наше программное обеспечение с Wix. Наша установка также устанавливает службу Windows. Чтобы позволить пользователям изменять информацию для входа в систему для службы Windows, мы хотим устанавливать службу только при первой установке и удалять только при удалении. Для обновлений мы вручную останавливаем службу, чтобы файлы могли быть обновлены.
У нас это работает, но недавно мы обнаружили, что на некоторых машинах служба Windows удаляется во время UnpublishFeatures:
Это если из журнала неудачных обновлений:
Action 13:41:38: UnpublishFeatures. Unpublishing Product Features
MSI (s) (D8:EC) [13:41:38:346]: Executing op: FeatureUnpublish(Feature=Main,,Absent=2,Component=
UnpublishFeatures: Feature: Main
MSI (s) (D8:EC) [13:41:38:346]: Note: 1: 1402 2: UNKNOWN\Installer\Features\84B659030632F794E93A7CB19A87DB8E 3: 2
MSI (s) (D8:EC) [13:41:38:346]: Executing op: ActionStart(Name=StopServices,Description=Stopping services,Template=Service: [1])
Action 13:41:38: StopServices. Stopping services
MSI (s) (D8:EC) [13:41:38:362]: Executing op: ProgressTotal(Total=1,Type=1,ByteEquivalent=1300000)
MSI (s) (D8:EC) [13:41:38:362]: Executing op: ServiceControl(,Name=RidderIQWebApi,Action=2,Wait=1,)
StopServices: Service: Ridder iQ Web API
MSI (s) (D8:EC) [13:41:38:393]: Executing op: ActionStart(Name=DeleteServices,Description=Deleting services,Template=Service: [1])
Action 13:41:38: DeleteServices. Deleting services
MSI (s) (D8:EC) [13:41:38:393]: Executing op: ProgressTotal(Total=1,Type=1,ByteEquivalent=1300000)
MSI (s) (D8:EC) [13:41:38:393]: Executing op: ServiceControl(,Name=RidderIQWebApi,Action=8,Wait=1,)
DeleteServices: Service: Ridder iQ Web API
Это если из лога от успешного обновления:
Action 11:53:24: UnpublishFeatures. Unpublishing Product Features
MSI (s) (CC:3C) [11:53:24:976]: Executing op: FeatureUnpublish(Feature=Main,,Absent=2,Component=
UnpublishFeatures: Feature: Main
MSI (s) (CC:3C) [11:53:24:977]: Note: 1: 1402 2: UNKNOWN\Installer\Features\84B659030632F794E93A7CB19A87DB8E 3: 2
MSI (s) (CC:3C) [11:53:24:978]: Executing op: ActionStart(Name=RemoveFiles,Description=Removing files,Template=File: [1], Directory: [9])
Action 11:53:24: RemoveFiles. Removing files
Как вы видите, установщик Windows пропускает действия StopServices/DeleteServices и начинает удаление файлов. Поскольку служба удаляется в UnpublishFeatures позже во время установки, она пытается настроить службу, но не удается, потому что она больше не установлена:
MSI (s) (D8:68) [13:42:34:772]: Executing op: CustomActionSchedule(Action=ExecServiceConfig,ActionType=3073,Source=BinaryData,Target=ExecServiceConfig,CustomActionData=)
MSI (s) (D8:90) [13:42:34:772]: Invoking remote custom action. DLL: C:\Windows\Installer\MSI170B.tmp, Entrypoint: ExecServiceConfig
ExecServiceConfig: Error 0x80070424: Service 'RidderIQWebApi' does not exist on this system.
ExecServiceConfig: Error 0x80070424: Failed to get service: RidderIQWebApi
CustomAction ExecServiceConfig returned actual error code 1603 (note this may not be 100% accurate if translation happened inside sandbox)
Action ended 13:42:35: InstallFinalize. Return value 3.
Я предполагаю, что это происходит потому, что действие для компонента отличается для обоих обновлений, для неудачного обновления это действия компонента:
MSI (s) (D8:68) [13:41:26:400]: Component: cmp.SR.SDKWebAPI.Service.exe; Installed: Absent; Request: Local; Action: Local
MSI (s) (D8:EC) [13:41:36:400]: Component: cmp.SR.SDKWebAPI.Service.exe; Installed: Local; Request: Absent; Action: Absent
Для успешного обновления это действия компонента:
MSI (s) (CC:44) [11:53:17:386]: Component: cmp.SR.SDKWebAPI.Service.exe; Installed: Absent; Request: Local; Action: Local
MSI (s) (CC:3C) [11:53:22:850]: Component: cmp.SR.SDKWebAPI.Service.exe; Installed: Local; Request: Absent; Action: FileAbsent
Как видите, действие для неудачного обновления - Отсутствует, а для успешного обновления - FileAbsent. Из того, что я прочитал, FileAbsent означает, что функция переустановлена, а Absent означает, что функция будет удалена.
У меня вопрос, как определяются действия для компонентов, и почему это происходит на одном компьютере, а на другом - FileAbsent. И есть ли способ это исправить?
Компонент, если настроен так:
<Component Id="cmp.SR.SDKWebAPI.Service.exe" Guid="">
<File Id="fil.SDKWebAPI.Service.exe" Source="SDKWebAPI.Service.exe" KeyPath="yes" />
<File Id="fil.SDKWebAPI.Service.exe.config" Source="SDKWebAPI.Service.exe.config" KeyPath="no" />
<ServiceInstall Id="SDKWebAPI.Service.exe.Installer"
Type="ownProcess"
Name="RidderIQWebApi"
DisplayName="Ridder iQ Web API"
Description="Ridder iQ Web API service"
Start="auto"
Account="LocalSystem"
ErrorControl="ignore">
<util:ServiceConfig FirstFailureActionType="restart"
SecondFailureActionType="restart"
ThirdFailureActionType="restart"
RestartServiceDelayInSeconds="60"
ResetPeriodInDays="0" />
</ServiceInstall>
</Component>
1 ответ
Пустой GUID компонента: Guid=""
это то, что вы недавно установили? Это, как я полагаю, установит пустой GUID для компонента, а это означает, что он будет установлен при первой установке и никогда не будет затронут или обновлен после этого (если вы не нашли какой-то хитрости для переустановки компонента при обновлении) - и это не будет удален либо, насколько я помню.
Поздний ответ: выше (пустой GUID) не похоже на то, что вы намерены. Вы просто хотите, чтобы компонент не удалялся при серьезном обновлении, и в этом случае вы обычно будете перемещать RemoveExistingProducts
поздно в InstallExecuteSequence
- то, что требует, чтобы вы следовали всем правилам компонента к письму. Это очень сложное поведение во время выполнения, но простая концепция. По сути, ваша новая версия будет установлена в виде патча - перезаписывая файлы без их предварительного удаления, что позволит сохранить ваши учетные данные службы, поскольку компонент, на котором размещается служба, никогда не удаляется.
Ранний REP: Просто для справки, обычный способ сделать серьезные обновления - это запланировать RemoveExistingProducts
в начале InstallExecuteSequence
Это означает, что все файлы удалены, а затем переустановлены. Этот подход используется потому, что он допускает небрежные ссылки на компоненты. Он известен за уничтожение пользовательских данных, таких как лицензионные ключи, учетные данные службы и т. Д.
Постоянный компонент. Другой подход - установить постоянный компонент хостинга. Тогда он никогда не будет удален во время серьезного обновления (даже если вы используете ранний REP), но также и во время обычной деинсталляции, что приводит к нахождению соответствующих файлов в системе (если вы не добавите свои собственные, настраиваемые функции очистки - который может быть очень подвержен ошибкам).
Механизм резервного копирования настраиваемых действий. Другие полагаются на собственные настраиваемые действия ( пример) для резервного копирования данных, которые удаляются во время обновления, а затем повторно применяют их после завершения обновления. На мой взгляд, очень подверженный ошибкам подход.
MSI только для службы: вы также можете поместить установку службы в ее собственный MSI, чтобы сделать его обновление более управляемым для вас - или в случае, если нельзя выполнить основную настройку для соблюдения правил компонента. Это также несколько сложно, но лучше, чем пользовательские действия, на мой взгляд.
Незначительное обновление: если вы можете использовать незначительные обновления для установки обновлений, вы можете избежать этой проблемы с учетными данными службы. Я просто сошлюсь на другой ответ, который описывает это: Перезапуск службы Windows во время обновления WIX.
(Управляемые) учетные записи службы: для запуска службы можно использовать обычную учетную запись службы без ( учетных записей службы), например LocalService, LocalSystem или NetworkService (что, очевидно, для вас невозможно, я бы предположил). Или более новые концепции управляемых учетных записей служб, групповых учетных записей управляемых служб или виртуальных учетных записей с пошаговой информацией (концепции, о которых я не знаю достаточно).
Другие подходы: несомненно, есть и другие подходы. Я полагаю, вы могли бы сохранить конфигурацию службы вне MSI и применить ее через скрипт. Я бы не рекомендовал это. Я знаю, что некоторые люди переключаются между использованием служб и запланированными задачами в зависимости от характера выполняемой задачи (по сути, переключаются на запланированные задачи, если это задача, которая запускается только время от времени). Хотя это и рискованно, я полагаю, вы могли бы отложить настройку службы на EXE-файл с повышенными правами, который пользователь запускает после установки (в данном случае, очевидно, пользователь должен быть администратором), который затем мог бы настроить конфигурацию с некоторой интерактивностью (сообщения об ошибках и статусе непосредственно в пользователь - и не просто скрытый в журналах), который иногда может помочь людям двигаться вперед. Не мой рекомендуемый подход - повышенные действия - это то, для чего нужна установка. Любая не повышенная конфигурация, которую я люблю делать в приложении.
Распространенные проблемы MSI в реальном мире. Я писал о некоторых типичных проблемах, возникающих в практическом применении MSI некоторое время назад, и вот он: Как мне избежать типичных ошибок проектирования в моем решении развертывания WiX / MSI? Это не здорово. Я не очень доволен этим - его не хватает во многих отношениях, но он есть на тот случай, если он может помочь. Это было лучшее усилие в доступное время. Пожалуйста, примите его таким, какой он есть: незавершенный дамп реальных проблем с несколькими указателями здесь и там для того, что вы можете попытаться решить проблему.