【问题标题】:Wix: Windows Service sometimes uninstalled when upgradingWix:升级时有时会卸载 Windows 服务
【发布时间】:2018-05-16 07:26:49
【问题描述】:

我们使用 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 Installer 会跳过 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

如您所见,升级失败的操作是 Absent,升级成功的操作是 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>

【问题讨论】:

  • 我在下面快速转储了一些信息。可能我没有认真阅读您的问题,请检查答案,然后我们可以解决任何误解。
  • 停止/启动/删除服务由 ServiceControl 管理,因此如果您正在使用它们,请发布您的 ServiceControl 内容。此外,升级的行为也会因主要升级的顺序而有所不同,因此也请提供该信息。完整的失败日志也会比您提供的区域更有用。

标签: windows service wix


【解决方案1】:

空白组件 GUIDGuid="" 这是你最近设置的吗?我相信,这将为组件设置一个空白 GUID,这意味着它将在第一次安装时安装,之后永远不会触及或升级(除非你找到了一些技巧来在升级时重新安装组件) - 它不会据我记得,都卸载了。

延迟 REP:上面的(空白 GUID)看起来不像你想要的。您只希望组件在重大升级时不卸载,在这种情况下,您通常会在 InstallExecuteSequence 的后期移动 RemoveExistingProducts - 这需要您严格遵守所有组件规则。这是非常复杂的运行时行为,但却是一个简单的概念。本质上,您的新版本将作为补丁安装 - 覆盖文件而不先卸载它们 - 允许保留您的服务凭据,因为托管服务的组件永远不会被卸载。

早期 REP:仅作记录,进行重大升级的常用方法是在 InstallExecuteSequence 的早期安排 RemoveExistingProducts,这意味着所有文件都已卸载,然后重新安装。使用这种方法是因为它允许草率的组件引用。它以清除用户数据(如许可证密钥、服务凭证等)而闻名......

永久组件:另一种方法是将托管组件设置为永久。然后它永远不会在重大升级期间被卸载(即使您使用早期 REP),但也不会在常规卸载期间被卸载,因此将有问题的文件搁置在系统上(除非您添加自己的自定义清理功能 -这很容易出错)。

自定义操作备份机制:其他人依靠自己的自定义操作 (example) 备份在升级过程中被清除的数据,然后在升级后重新应用它们升级完成。 在我看来,这是一种非常容易出错的方法

Service Only MSI:您还可以将服务安装放在其自己的 MSI 中,以使其更新对您更可控 - 或者在主设置无法控制的情况下遵守组件规则。这也有点复杂,但在我看来比自定义操作要好。

次要升级:如果您可以使用次要升级来安装升级,则可以避免此服务凭据问题。我将链接到另一个描述此问题的答案:Restarting windows service during WIX upgrade

(托管)服务帐户:您可以使用没有 (about service accounts) 凭据的常规服务帐户来运行服务 - 例如 LocalService、@987654325 @ 或 NetworkService (我想这显然对你来说是不可能的)。或者managed service accountsgroup managed service accounts 或虚拟帐户step-by-step info 的较新概念(我不太了解的概念)。

其他方法:毫无疑问还有其他方法。我想您可以将服务配置排除在 MSI 之外并通过脚本应用它。我不会推荐它。我知道有些人根据the nature of the task at hand 在使用服务计划任务 之间切换(如果是task that runs only once in a while,则基本上切换到计划任务)。虽然有风险,但我想您可以将服务配置推迟到用户在安装后启动的提升的 EXE(显然,在这种情况下,用户必须是管理员),然后可以设置具有一些交互性的配置(错误和状态消息直接发送到用户 - 而不仅仅是隐藏在日志中)有时可以帮助人们继续前进。虽然不是我推荐的方法 - 提升操作是设置的目的。我喜欢在应用程序中进行的任何非提升配置。


Common Real-World MSI Problems:我写了一些在 MSI 实际应用中看到的常见问题,这里是:How do I avoid common design flaws in my WiX / MSI deployment solution?这不是很好。我对它不是很满意——它在很多方面都缺乏——但它确实存在,以防万一它可以提供帮助。这是在可用时间内的最大努力。请接受它的本质:现实世界问题的未完成转储,在这里和那里有一些提示,您可以尝试解决问题。


链接

【讨论】:

  • 是否有关于如何进行“早期 REP”的文档?
猜你喜欢
  • 2018-10-28
  • 1970-01-01
  • 2018-05-14
  • 1970-01-01
  • 2011-02-27
  • 1970-01-01
  • 1970-01-01
  • 2010-09-24
  • 1970-01-01
相关资源
最近更新 更多