在工作中,我们使用WiX来构建安装包。我们希望产品 X 的安装会导致在该机器上卸载该产品的先前版本。
我在 Internet 上的几个地方阅读了有关重大升级的信息,但无法使其正常工作。任何人都可以指定将卸载以前版本功能添加到 WiX 需要采取的确切步骤吗?
在工作中,我们使用WiX来构建安装包。我们希望产品 X 的安装会导致在该机器上卸载该产品的先前版本。
我在 Internet 上的几个地方阅读了有关重大升级的信息,但无法使其正常工作。任何人都可以指定将卸载以前版本功能添加到 WiX 需要采取的确切步骤吗?
最后我找到了一个解决方案 - 我在这里为可能有同样问题的其他人(你们 5 个人)发布它:
在产品下添加以下内容:
<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
在最新版本中(从 3.5.1315.0 测试版开始),您可以使用MajorUpgrade 元素而不是使用您自己的元素。
例如,我们使用此代码进行自动升级。它可以防止降级,提供本地化错误消息,还可以防止升级已经存在的相同版本(即仅升级较低版本):
<MajorUpgrade
AllowDowngrades="no" DowngradeErrorMessage="!(loc.NewerVersionInstalled)"
AllowSameVersionUpgrades="no"
/>
以下是我用于重大升级的语法:
<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 必须相同。
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
你最好在WiX 用户邮件列表上问这个问题。
最好在充分了解 Windows Installer 正在做什么的情况下使用 WiX。您可以考虑获取“ Windows Installer 权威指南”。
删除现有产品的操作是RemoveExistingProducts 操作。因为它所做的事情的后果取决于它的计划位置 - 即故障是否导致旧产品被重新安装,以及是否再次复制未更改的文件 - 您必须自己安排它。
RemoveExistingProducts
处理<Upgrade>
当前安装中的元素,将@Id
属性与系统上所有已安装产品的UpgradeCode
(在元素中指定)相匹配。<Product>
定义了UpgradeCode
一系列相关产品。任何具有此 UpgradeCode 的产品,其版本在指定范围内,以及该UpgradeVersion/@OnlyDetect
属性所在no
(或被省略)的位置,都将被删除。
RemoveExistingProducts
提及设置UPGRADINGPRODUCTCODE
属性的文档。这意味着要删除的产品的卸载过程会收到该属性,该属性的值是Product/@Id
要安装的产品的值。
如果您的原始安装不包含UpgradeCode
,您将无法使用此功能。
我使用这个网站来帮助我了解有关 WiX 升级的基础知识:
http://wix.tramontana.co.hu/tutorial/upgrades-and-modularization
之后我创建了一个示例安装程序(安装了一个测试文件),然后创建了升级安装程序(安装了 2 个示例测试文件)。这将使您对该机制的工作原理有一个基本的了解。
正如迈克在 Apress 的书“Windows 安装程序权威指南”中所说,它将帮助您理解,但它不是使用 WiX 编写的。
另一个很有帮助的网站是这个:
我阅读了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 ”参数进行次要和小型升级,但并没有说这些参数对于重大升级是禁止的- 它们只是停止工作。因此,您不应将它们用于重大升级。
我建议看看 Alex Shevchuk 的教程。他在From MSI to WiX, Part 8 - Major Upgrade中通过一个很好的动手示例解释了通过 WiX 进行的“重大升级” 。
我从教程中错过了一段时间(从http://www.tramontana.co.hu/wix/lesson4.php窃取)导致“已安装此产品的另一个版本”错误的一件重要事情:
*小幅更新 是指对一个或几个文件进行小幅改动,而这些改动不需要更改产品版本(major.minor.build)。您也不必更改产品 GUID。请注意,当您创建一个在任何方面都与以前不同的新 .msi 文件时,您始终必须更改包 GUID。安装程序会跟踪您已安装的程序,并在用户想要使用这些 GUID 更改或删除安装时找到它们。对不同的包使用相同的 GUID 会使安装程序感到困惑。
次要升级 表示产品版本已经更改的更改。修改 Product 标签的 Version 属性。产品将保持不变,因此您无需更改产品 GUID,但当然可以获取新的包 GUID。
重大升级 表示重大变化,例如从一个完整版本升级到另一个完整版本。更改所有内容:版本属性、产品和包 GUID。
我正在使用最新版本的 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 相同。
下面为我工作。
<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 匹配。
这对我有用,即使是主要的DOWN等级:
<Wix ...>
<Product ...>
<Property Id="REINSTALLMODE" Value="amus" />
<MajorUpgrade AllowDowngrades="yes" />