如何使WIX MSI始终删除先前的版本?

28

我有一个CI构建系统,每当开发人员检查更改时,就会构建一个MSI。我们在安装的MSI上运行自动化验收测试。

基本上,每个MSI都是产品的完整安装包,因此我们没有任何版本控制(类似于Windows Installer)。

每个MSI具有相同的产品GUID和升级GUID以及相同的版本号,但具有不同的软件包GUID(在wix中使用“*”)。

我想实现的是,在安装程序运行时,它将“卸载”先前安装的产品版本,并安装新版本...全部通过单个MSI进行(我们有一个复杂的安装过程,超出了我们的控制范围..citrix和sccm,因此我们希望为他们提供简单的安装路径)

我尝试过:

<Property Id='PREVIOUSVERSIONSINSTALLED' Secure='yes' />
<Upgrade Id='$UPGRADE_GUID'>  
  <UpgradeVersion Minimum='1.0.0.0'
                  Maximum='99.0.0.0'
                  Property='PREVIOUSVERSIONSINSTALLED'
                  IncludeMinimum='yes'
                  IncludeMaximum='no' />
</Upgrade>

并且具有:

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

我已经尝试过:

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

但是当我尝试安装之后一个版本的msi时,会出现以下情况:

Another version of this product is already installed. Installation of this version cannot continue. 
To configure or remove the existing version of this product, use Add/Remove Programs on the Control Panel. 

这并不是我想要的...

我知道我可以只更新产品标签中的版本属性,但这样很难管理。首先,我每天可以生成20多个MSI构建,因为我有许多构建流水线会生成MSI,我不确定如何以一种合理的方式处理版本编号。

也许Windows Installer根本不允许这种“始终覆盖已安装版本”的安装方式?

4个回答

30
你可以使用此代码来删除旧版本并安装更新的版本:
<Product Id="*"
         UpgradeCode="87795f3dc95-81f5-473e-955e-2871a5bd66a5"
         Name="AppName"
         Language="1033"
         Version="1.0.6"
         Manufacturer="Manufacturer Name">
  <Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
  <MajorUpgrade Schedule="afterInstallInitialize"
                DowngradeErrorMessage="A later version of [ProductName] is already installed"
                AllowSameVersionUpgrades="yes" />
</Product>

1
是否需要移除现有产品 RemoveExistingProducts? - kudlatiger
5
@kudlatiger 是的!关键是设置 AllowSameVersionUpgrades="yes"。 - Shannon

30

所以我找到了一种方法,在不更改版本号的情况下完成了它。

我每次构建时改变产品GUID,但保持升级GUID不变。

我还必须将RemoveExistingProducts更改为Before='InstallInitialize'。否则,它只会在安装路径中留下构建之间的“增量”。

如Wim所述,我可以用'*'替换生成的产品GUID。


23
不需要手动更改产品 GUID,你可以(而且应该)将其设置为"*"。 - Wim Coenen
你对包ID做了什么? - benstpierre
我知道这是一个老问题。有没有办法停止它,以便您可以更改设置? - Linda Lawton - DaImTo
不确定 @DaImTo。自 2012 年以来,我就没有涉及过这方面的东西了! - grillp

6

谢谢Daniel,那个链接是我最初尝试的...我忘了提到我已经有了RemoveExistingProducts,但我把它放在了After='InstallInitialize'。现在我已经尝试了After='InstallFinalize',但结果还是一样。 :-( - grillp
2
@DanielPowell:根据你提供的链接,应该是 Before="InstallInitialize" - c00000fd

4
如果产品代码和版本相同,但包代码不同,您将始终收到Windows Installer错误消息。
我强烈建议在CI构建中包含安装程序的版本信息。如果您正在安装并随后升级每个构建,则具有版本控制并不是坏事。将此添加到CI构建应该相对容易。

Bryan,没问题,我可以这么做。你知道版本号的限制是多少吗?是255.255.255.255还是更大? - grillp
请查看此链接:http://msdn.microsoft.com/zh-cn/library/windows/desktop/aa370859(v=vs.85).aspx - BryanJ
1
我喜欢将源代码控制修订号作为第三位数字包含进去。 - BryanJ
谢谢你的回复。就像我说的,我有很多构建流水线,但只有主构建流水线的结果会进入生产环境。因此,我可以使用那个流水线的构建编号。其他的是开发人员分支(呃!多个开发分支合并到主分支……别问为什么!),所以它们可以手动卸载和重新安装。 - grillp
顺便说一句,关于版本号的问题我有点懒,应该直接查一下的。 - grillp
另一个选择可能是更改产品代码。 我在每次构建时更改产品代码,但是像我所说的那样,我总是增加版本号。 您可以尝试每次更改产品代码并编辑安装程序以处理该升级。 - BryanJ

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接