Wix: служба Windows иногда удаляется при обновлении - PullRequest
0 голосов
/ 16 мая 2018

Мы устанавливаем наше программное обеспечение с 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 Ответ

0 голосов
/ 16 мая 2018

Пустой GUID компонента : Guid="" это то, что вы недавно установили? Это, как я полагаю, установит пустой GUID для компонента, а это означает, что он будет установлен при первой установке и никогда не будет затронут или обновлен после этого (если вы не нашли какой-то хитрости для переустановки компонента при обновлении) - и это не будет удалено либо, насколько я помню.

Поздний REP : Вышеуказанное (пустой GUID) не похоже на то, что вы намереваетесь. Вы просто хотите, чтобы компонент не удалялся при серьезном обновлении, и в этом случае вы обычно двигались бы на RemoveExistingProducts в конце InstallExecuteSequence - то, что требует от вас следовать всем правилам компонента к букве. Это очень сложное поведение во время выполнения, но простая концепция. По сути, ваша новая версия будет установлена ​​в виде патча - перезаписывая файлы, не удаляя их в первую очередь, - позволяя сохранить учетные данные службы, поскольку компонент, на котором размещается служба, никогда не удаляется.

Ранний REP : Просто для записи, общий способ сделать основные обновления - это запланировать RemoveExistingProducts в начале InstallExecuteSequence, что означает, что все файлы удалены, и затем переустановил. Этот подход используется потому, что он допускает небрежные ссылки на компоненты. Он известен за уничтожение пользовательских данных, таких как лицензионные ключи, учетные данные службы и т. Д. *

Постоянный компонент : Другой подход - установить постоянный компонент хостинга. Тогда он никогда не будет удален во время серьезного обновления (даже если вы ранее использовали REP), но также и во время обычной деинсталляции, что приведет к нахождению соответствующих файлов в системе (если вы не добавите свои собственные, настраиваемые функции очистки - который может быть очень подвержен ошибкам).

Механизм резервного копирования пользовательских действий : Другие полагаются на свои собственные пользовательские действия ( пример ) для резервного копирования данных, которые стираются во время обновления, а затем повторно применяются их после завершения обновления. На мой взгляд, очень подверженный ошибкам подход .

Служба только MSI : Вы также можете поместить установку службы в собственный MSI, чтобы сделать ее обновление более управляемым для вас - или в случае, если не удастся выполнить основную настройку соблюдать правила компонента. Это также несколько сложно, но, на мой взгляд, лучше, чем пользовательские действия.

Незначительное обновление : если вы можете использовать незначительные обновления для установки обновлений, вы можете избежать этой проблемы с учетными данными службы. Я просто сошлюсь на другой ответ, который описывает это: Перезапуск службы Windows во время обновления WIX .

(управляемые) учетные записи служб : для запуска службы можно использовать обычную учетную запись службы без учетных данных ( о служебных учетных записях ) - например, LocalService , LocalSystem или NetworkService (что, очевидно, для вас невозможно, я бы предположил). Или более новые концепции управляемых учетных записей служб , групповых учетных записей управляемых служб или виртуальных учетных записей пошаговая информация (концепции, о которых я недостаточно знаю) .

Другие подходы : Без сомнения, существуют и другие подходы. Я полагаю, вы могли бы сохранить конфигурацию службы вне MSI и применить ее через скрипт. Я бы не рекомендовал это. Я знаю, что некоторые люди переключаются между службами и запланированными задачами в зависимости от характера выполняемой задачи (по сути, переключаясь на запланированные задачи, если это задача, которая запускается только время от времени ). Хотя это и рискованно, я полагаю, вы могли бы отложить настройку службы на EXE-файл с повышенными правами, который пользователь запускает после установки (в данном случае, очевидно, пользователь должен быть администратором), который затем мог бы настроить конфигурацию с некоторой интерактивностью (сообщения об ошибках и статусе непосредственно в пользователь - и не просто скрытый в журналах), который иногда может помочь людям двигаться вперед. Не мой рекомендуемый подход - повышенные действия - это то, для чего нужна установка. Любая не повышенная конфигурация, которую я хотел бы сделать в приложении.


Распространенные проблемы MSI в реальном мире : Я писал о некоторых общих проблемах, возникающих при практическом применении MSI некоторое время назад, и вот он: Как Я избегаю общих недостатков дизайна в своем решении развертывания WiX / MSI? Это не здорово. Я не очень доволен этим - его не хватает во многих отношениях, но он есть, если он может помочь. Это было лучшее усилие в доступное время. Пожалуйста, примите это за то, что оно есть: незаконченный дамп реальных проблем с несколькими указателями здесь и там для того, что вы можете попытаться решить проблему.

...