243

在工作中,我们使用WiX来构建安装包。我们希望产品 X 的安装会导致在该机器上卸载该产品的先前版本。

我在 Internet 上的几个地方阅读了有关重大升级的信息,但无法使其正常工作。任何人都可以指定将卸载以前版本功能添加到 WiX 需要采取的确切步骤吗?

4

12 回答 12

225

最后我找到了一个解决方案 - 我在这里为可能有同样问题的其他人(你们 5 个人)发布它:

  • 将产品 ID 更改为 *
  • 在产品下添加以下内容:

    <Property Id="PREVIOUSVERSIONSINSTALLED" Secure="yes" />
    <Upgrade Id="YOUR_GUID">  
       <UpgradeVersion
          Minimum="1.0.0.0" Maximum="99.0.0.0"
          Property="PREVIOUSVERSIONSINSTALLED"
          IncludeMinimum="yes" IncludeMaximum="no" />
    </Upgrade> 
    
  • 在 InstallExecuteSequence 添加:

    <RemoveExistingProducts Before="InstallInitialize" /> 
    

从现在开始,每当我安装产品时,它都会删除以前安装的版本。

注意:将升级 ID 替换为您自己的 GUID

于 2008-09-22T13:03:32.667 回答
210

在最新版本中(从 3.5.1315.0 测试版开始),您可以使用MajorUpgrade 元素而不是使用您自己的元素。

例如,我们使用此代码进行自动升级。它可以防止降级,提供本地化错误消息,还可以防止升级已经存在的相同版本(即仅升级较低版本):

<MajorUpgrade
    AllowDowngrades="no" DowngradeErrorMessage="!(loc.NewerVersionInstalled)"
    AllowSameVersionUpgrades="no"
    />
于 2010-08-26T13:57:27.633 回答
89

以下是我用于重大升级的语法:

<Product Id="*" UpgradeCode="PUT-GUID-HERE" Version="$(var.ProductVersion)">
 <Upgrade Id="PUT-GUID-HERE">
    <UpgradeVersion OnlyDetect="yes" Minimum="$(var.ProductVersion)" Property="NEWERVERSIONDETECTED" IncludeMinimum="no" />
    <UpgradeVersion OnlyDetect="no" Maximum="$(var.ProductVersion)" Property="OLDERVERSIONBEINGUPGRADED" IncludeMaximum="no" />
</Upgrade>

<InstallExecuteSequence>
    <RemoveExistingProducts After="InstallInitialize" />
</InstallExecuteSequence>

正如@Brian Gillespie 所指出的,还有其他地方可以根据所需的优化安排 RemoveExistingProducts 。请注意 PUT-GUID-HERE 必须相同。

于 2009-04-07T04:05:23.947 回答
40

Product 元素中的 Upgrade 元素与适当的操作调度相结合,将执行您所追求的卸载。请务必列出您要删除的所有产品的升级代码。

<Property Id="PREVIOUSVERSIONSINSTALLED" Secure="yes" />
<Upgrade Id="00000000-0000-0000-0000-000000000000">
  <UpgradeVersion Minimum="1.0.0.0" Maximum="1.0.5.0" Property="PREVIOUSVERSIONSINSTALLED" IncludeMinimum="yes" IncludeMaximum="no" />
</Upgrade>

请注意,如果您对构建非常小心,您可以防止人们意外地安装旧版本的产品而不是新版本的产品。这就是最大字段的用途。当我们构建安装程序时,我们将 UpgradeVersion Maximum 设置为正在构建的版本,但 IncludeMaximum="no" 以防止出现这种情况。

您可以选择有关 RemoveExistingProducts 的计划。我更喜欢在 InstallFinalize 之后安排它(而不是像其他人推荐的那样在 InstallInitialize 之后):

<InstallExecuteSequence>
  <RemoveExistingProducts After="InstallFinalize"></RemoveExistingProducts>
</InstallExecuteSequence>

这会在复制新文件和注册表项之前一直安装先前版本的产品。这让我可以将数据从旧版本迁移到新版本(例如,您已将用户首选项的存储从注册表切换到 XML 文件,但您想保持礼貌并迁移他们的设置)。此迁移在 InstallFinalize 之前的延迟自定义操作中完成。

另一个好处是效率:如果有未更改的文件,当您在 InstallFinalize 之后安排时,Windows Installer 不会再次复制它们。如果在 InstallInitialize 之后调度,则先完全删除以前的版本,然后再安装新版本。这会导致不必要的文件删除和重新复制。

有关其他计划选项,请参阅 MSDN 中的 RemoveExistingProducts 帮助主题。本周,链接为:http: //msdn.microsoft.com/en-us/library/aa371197.aspx

于 2008-10-18T05:56:37.167 回答
16

你最好在WiX 用户邮件列表上问这个问题。

最好在充分了解 Windows Installer 正在做什么的情况下使用 WiX。您可以考虑获取“ Windows Installer 权威指南”。

删除现有产品的操作是RemoveExistingProducts 操作。因为它所做的事情的后果取决于它的计划位置 - 即故障是否导致旧产品被重新安装,以及是否再次复制未更改的文件 - 您必须自己安排它。

RemoveExistingProducts处理<Upgrade>当前安装中的元素,将@Id属性与系统上所有已安装产品的UpgradeCode(在元素中指定)相匹配。<Product>定义了UpgradeCode一系列相关产品。任何具有此 UpgradeCode 的产品,其版本在指定范围内,以及该UpgradeVersion/@OnlyDetect属性所在no(或被省略)的位置,都将被删除。

RemoveExistingProducts提及设置UPGRADINGPRODUCTCODE属性的文档。这意味着要删除的产品的卸载过程会收到该属性,该属性的值是Product/@Id要安装的产品的值。

如果您的原始安装不包含UpgradeCode,您将无法使用此功能。

于 2008-09-22T13:14:56.633 回答
11

我使用这个网站来帮助我了解有关 WiX 升级的基础知识:

http://wix.tramontana.co.hu/tutorial/upgrades-and-modularization

之后我创建了一个示例安装程序(安装了一个测试文件),然后创建了升级安装程序(安装了 2 个示例测试文件)。这将使您对该机制的工作原理有一个基本的了解。

正如迈克在 Apress 的书“Windows 安装程序权威指南”中所说,它将帮助您理解,但它不是使用 WiX 编写的。

另一个很有帮助的网站是这个:

http://www.wixwiki.com/index.php?title=Main_Page

于 2008-09-24T15:56:01.177 回答
10

我阅读了WiX文档,下载了示例,但我仍然遇到很多升级问题。尽管可以指定这些卸载,但次要升级不会执行以前产品的卸载。我花了更多的时间进行调查,发现 WiX 3.5 引入了一个新的升级标签。这是用法:

<MajorUpgrade Schedule="afterInstallInitialize"
        DowngradeErrorMessage="A later version of [ProductName] is already installed. Setup will now exit." 
        AllowDowngrades="no" />

但问题的主要原因是文档说使用“ REINSTALL=ALL REINSTALLMODE=vomus ”参数进行次要和小型升级,但并没有说这些参数对于重大升级是禁止的- 它们只是停止工作。因此,您不应将它们用于重大升级。

于 2011-12-16T12:19:44.153 回答
7

我建议看看 Alex Shevchuk 的教程。他在From MSI to WiX, Part 8 - Major Upgrade中通过一个很好的动手示例解释了通过 WiX 进行的“重大升级” 。

于 2009-06-25T06:52:23.583 回答
7

我从教程中错过了一段时间(从http://www.tramontana.co.hu/wix/lesson4.php窃取)导致“已安装此产品的另一个版本”错误的一件重要事情:

*小幅更新 是指对一个或几个文件进行小幅改动,而这些改动不需要更改产品版本(major.minor.build)。您也不必更改产品 GUID。请注意,当您创建一个在任何方面都与以前不同的新 .msi 文件时,您始终必须更改包 GUID。安装程序会跟踪您已安装的程序,并在用户想要使用这些 GUID 更改或删除安装时找到它们。对不同的包使用相同的 GUID 会使安装程序感到困惑。

次要升级 表示产品版本已经更改的更改。修改 Product 标签的 Version 属性。产品将保持不变,因此您无需更改产品 GUID,但当然可以获取新的包 GUID。

重大升级 表示重大变化,例如从一个完整版本升级到另一个完整版本。更改所有内容:版本属性、产品和包 GUID。

于 2010-12-24T10:52:46.050 回答
5

我正在使用最新版本的 WiX (3.0) 并且无法使上述工作正常进行。但这确实有效:

<Product Id="*" UpgradeCode="PUT-GUID-HERE" ... >

<Upgrade Id="PUT-GUID-HERE">
  <UpgradeVersion OnlyDetect="no" Property="PREVIOUSFOUND"
     Minimum="1.0.0.0"  IncludeMinimum="yes"
     Maximum="99.0.0.0" IncludeMaximum="no" />
</Upgrade>

请注意,PUT-GUID-HERE 应该与您在产品的 UpgradeCode 属性中定义的 GUID 相同。

于 2010-03-09T07:57:55.073 回答
3

下面为我​​工作。

<Product Id="*" Name="XXXInstaller" Language="1033" Version="1.0.0.0" 
    Manufacturer="XXXX" UpgradeCode="YOUR_GUID_HERE">
<Package InstallerVersion="xxx" Compressed="yes"/>
<Upgrade Id="YOUR_GUID_HERE">
    <UpgradeVersion Property="REMOVINGTHEOLDVERSION" Minimum="1.0.0.0" 
        RemoveFeatures="ALL" />
</Upgrade>
<InstallExecuteSequence>
    <RemoveExistingProducts After="InstallInitialize" />
</InstallExecuteSequence>

请确保 Product 中的 UpgradeCode 与 Upgrade 中的 Id 匹配。

于 2015-12-04T22:52:08.310 回答
1

这对我有用,即使是主要的DOWN等级:

<Wix ...>
  <Product ...>
    <Property Id="REINSTALLMODE" Value="amus" />
    <MajorUpgrade AllowDowngrades="yes" />
于 2014-03-24T19:40:40.187 回答