11

我正在努力让 MajorUpgrade、ServiceControl、.config 文件很好地协同工作。 在我的另一个问题之后,我现在又遇到了相反的问题。

之前,文件没有被覆盖,因为 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

4

2 回答 2

5

编辑:似乎对同一问题或至少在同一主题上的这种解释可能更容易理解:Msiexec:安装失败时自动回滚到以前的版本


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

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

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

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

于 2014-05-08T16:43:23.397 回答
4

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

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

于 2014-05-08T13:33:43.530 回答