【问题标题】:WiX MajorUpgrade of Windows Service, preserving .config, and avoiding a rebootWiX 主要升级 Windows 服务,保留 .config,避免重启
【发布时间】:2014-06-14 12:10:01
【问题描述】:

我正在努力让 MajorUpgrade、ServiceControl、.config 文件很好地协同工作。 After my other question,我现在又遇到了相反的问题。

之前,文件没有被覆盖,因为 AssemblyFileVersions 是静态的,所以我修复了这个问题。 1) 现在,即使使用Schedule="afterInstallExecute" 我的KeyPath='yes' .config 文件仍然被覆盖,即使现有文件的修改日期不同比文件创建日期,它被设置为 KeyPath。我目前不得不覆盖 .config 文件并在安装后重新启动服务。

2) 即使我解决了这个问题,我仍然遇到避免重启的问题。如果我说Schedule="afterInstallInitialize",那么我相信 .config 文件肯定会过早地与服务一起被删除。如果我说Schedule="afterInstallExecute",那么服务不会停止,安装后需要重新启动。 (没错,对吧?)在安装之前手动停止服务让我避免重新启动。我猜添加 net stop 自定义操作可以替换 ServiceControl,但正确设置所有条件似乎很复杂。

3)另外,我想在升级过程中根本不删除服务。我可以停止服务,替换二进制文件,然后重新启动服务吗?这将避免重新输入服务帐户凭据以进行升级。但当然,它仍然需要在首次安装时安装并在删除功能时卸载。

这是它的主要内容(稍后也会捆绑,以防万一重要):

<MajorUpgrade DowngradeErrorMessage="A newer version is already installed." 
              Schedule="afterInstallExecute" />

<ComponentGroup Id="ServiceCG">
    <Component Id="Service" Guid='*' Win64='yes' Directory='INSTALLDIR'>
        <File Id='ServiceEXE' Source='$(var.root)Service.exe' />
        <ServiceInstall Id="ServiceInstall"
                          Name="MyService"
                          DisplayName="My Server"
                          Type="ownProcess"
                          Start="auto"
                          ErrorControl="normal"
                          Description="My Server Service"
                          Interactive="no"
                          Account="[...]"
                          Password="[...]" />
        <ServiceControl Id="StopService" Name="MyService" Start="install" 
                        Stop="uninstall" Wait="yes" Remove="both" />
        <util:User Id="UpdateServiceAccountLogonAsService" UpdateIfExists="yes"
                   CreateUser="no" Name="[SERVICEACCOUNTFULL]" 
                   LogonAsService="yes"/>
    </Component>
    <Component Id="ServiceConfig" Guid='*' Win64='yes' Directory='INSTALLDIR'>
        <File Id='FileServiceConfig' KeyPath='yes' 
              Source='$(var.root)Service.exe.config' />
    </Component>
</ComponentGroup>

相关但未回答:

WiX 版本 3.8.1128.0

【问题讨论】:

  • 您使用的是哪个版本的 wix?知道这可能会帮助您获得有用的答案。
  • WiX 版本 3.8.1128.0
  • WiX 版本与这个问题并不真正相关。所有涉及的元素都映射到 Windows Installer 表,并且没有额外的自定义扩展。重要的是底层 MSI 行为。

标签: wix installation windows-installer major-upgrade


【解决方案1】:

编辑:似乎对同一问题或至少同一主题的这种解释可能更容易理解:Msiexec: automatic rollback to previous version on installation failure


您在这里遇到了几个核心 MSI 使用问题。

  1. 文件版本控制:在安装过程中,默认文件覆盖模式(由REINSTALLMODE property 定义)不会替换默认相同版本的文件。这可以通过设置 REINSTALLMODE = "emus" 来改变。这将为版本化文件替换具有相同版本的文件。如果修改日期和创建日期不同,将保留未版本化的文件。
  2. 升级行为:就像 Chris 所说,由于主要升级配置,看似恢复为默认值的文件实际上已被卸载并重新安装。如果将 RemoveExistingProducts 放在 InstallExecuteSequence 的后期,则仅在主要升级中才可能保留文件。然后版本之间的共享文件永远不会被卸载,并且第 1 点中描述的文件版本控制规则适用于覆盖。
  3. 服务配置保存:避免重新输入服务凭据信息是在 InstallExecuteSequence 中提前卸载的重大升级的常见问题。换句话说,该产品被卸载,然后重新安装清除更改的文件。我不推荐它,但有些人支持这个解决方案:How to only stop and not uninstall windows services when major upgrade in wix?Rob Mensching 是 WIX 和 Orca 的作者 - 我认为他建议将此解决方案作为一种选择,而不一定是推荐。请在链接的帖子中询问以确保)。通过在 InstallExecuteSequence 后期放置正确的组件引用和卸载,通常可以完全避免此问题,这是一种首选方法(正常的组件引用会阻止组件完全卸载,从而使服务设置和更改的配置文件保持不变 - 当且仅当, 组件引用 是正确的 - 请参阅下面对此概念的描述)。但是,我的首选方法仍然是使用单独的 MSI 进行服务安装和配置如果您使用用户帐户来运行服务 - 那么它是自包含的部署单元,可以包含在引导程序中并自行更新,最重要的是:它不受任何其他应用程序更改或修补程序的干扰。最后,我想指出,出于安全和部署等原因,不推荐使用用户帐户运行服务。

组件引用:指分配给 MSI 组件的 GUID,以及它们必须如何匹配,并且在所有升级中始终只有一个(绝对)路径。请在此处通过几个示例对此进行更好的讨论:Change my component GUID in wix?

我没有提到将安装服务的 MSI 组件设置为永久的选项,以防止在卸载时将其删除,原因很简单,这根本不是一个好习惯。然后文件和注册将在最终卸载时保留,您需要自定义操作来清理。非常糟糕的做法,必然会导致大量额外工作和悬空组件引用问题。

【讨论】:

  • 对于 1,如何对 .config 文件进行版本控制?我不相信覆盖REINSTALLMODE 是必要的。应该如何设置ServiceControl&lt;MajorUpgrade Schedule="afterInstallExecute" /&gt;,这样就不需要重新启动?升级时,服务是否在安装期间停止然后启动一次,在卸载期间再次启动?使用&lt;ServiceControl Start="both" Stop="both" Remove="both" /&gt;,不管Wait=yes/no,初始安装都会失败,因为当服务启动时,GAC 的程序集仍在 GAC Temp 目录中。
  • .config 文件没有版本控制。替换逻辑不会替换修改后的文件(创建和修改日期不同)。关于 GAC,请阅读此内容并认真评估您在 GAC 方面的优先事项:stackoverflow.com/questions/2451123/…
  • 这些程序集随着时间的推移进行版本控制,并在隔离的应用程序域中并行运行。
  • 我已经要求版主在这里奖励至少 25 个赏金点。你在这里付出了很多努力。谢谢。事情发生在最后一分钟,我出去了。
  • 这里有类似的解释,使用不同的焦点:Msiexec: automatic rollback to previous version on installation failure
【解决方案2】:

文件创建/修改规则仅适用于安装/重新安装组件。它不会阻止组件被卸载。您的主要升级安排得很早,这意味着完全卸载了以前的版本,然后安装了新版本。这就是为什么您的文件在您不期望的情况下被覆盖的原因。稍后安排 RemoveExistingProducts 以避免此问题。

将您的 Stop 属性设置为安装和卸载。这两项更改应该可以解决您的问题。

【讨论】:

  • ServiceControl 应该如何与 一起设置以便不需要重新启动?升级时,服务是否在安装过程中停止然后启动一次,在卸载过程中再次启动?使用 并且无论 Wait= yes/no,初始安装都会失败,因为当服务时 GAC 的程序集仍在 GAC Temp 目录中已启动。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-02-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多