如何实施WiX安装程序升级?

Dro*_*per 229 installer windows-installer wix

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

我已经在互联网上的几个地方读过有关重大升级的内容,但无法让它发挥作用.任何人都可以指定我需要采取的确切步骤,以便将卸载以前的版本功能添加到WiX吗?

Dro*_*per 219

最后我找到了一个解决方案 - 我在这里发布给其他可能遇到同样问题的人(所有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> 
    
    Run Code Online (Sandbox Code Playgroud)
  • 在InstallExecuteSequence下添加:

    <RemoveExistingProducts Before="InstallInitialize" /> 
    
    Run Code Online (Sandbox Code Playgroud)

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

注意:使用您自己的GUID替换升级ID

  • 是的,学习WiX就像试图找出某人决定"有意义"执行简单操作的晦涩咒语.有点像UNIX. (152认同)
  • 我认为你应该在那里编辑你的例子,以便没有实际的GUID.我相信人们会复制并粘贴它并逐字使用.也许使用"你的产品 - 升级 - 指导 - 这里"? (37认同)
  • 你的例子中有bug.MSI的`ProductVersion`仅支持三个版本字段; 因此,根本不会比较第四个字段.请参阅VersionMin和VersionMax下的说明,网址为http://msdn.microsoft.com/en-us/library/aa372379(VS.85).aspx (12认同)
  • @Antony,@ Dror Helper:我很确定你不应该使用"*"来生成新的GUID.内部的GUID(Upgrade Id ="")应该是硬编码和修复的,它应该与您的(Product UpgradeCode ="")属性中的GUID相匹配. (10认同)
  • 另外,"将产品ID更改为*"的确切做法是什么?它每次都会生成新产品ID吗?您的产品是否会产生不再具有固定ID的后果? - 听起来有点矫枉过正. (6认同)
  • 为什么没有"DontCareJustCopyTheFiles"元素? (6认同)
  • 请注意,这将删除已安装的_any_版本,即使它比您尝试安装的版本更新 (3认同)
  • 我的意思是,不要在升级ID中使用"*",但当然在产品ID中使用它作为Dror意图. (2认同)
  • 虽然升级似乎可以使用上面的方法,但在"添加删除程序"中我仍然可以看到旧版本(当然还有新版本).任何想法为什么会发生以及如何真正删除旧版本? (2认同)
  • 我完全按照建议做了,但这对我不起作用.如果我运行我的新安装,它只是忽略现有安装并安装一个新副本.我可能会缺少什么样的东西? (2认同)
  • 我似乎没有InstallExecuteSequence元素......(抓头). (2认同)

Ant*_*Ant 182

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

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

<MajorUpgrade
    AllowDowngrades="no" DowngradeErrorMessage="!(loc.NewerVersionInstalled)"
    AllowSameVersionUpgrades="no"
    />
Run Code Online (Sandbox Code Playgroud)

  • +1这个答案需要收到尽可能多的赞成票; 如果你的答案有5倍的赞成票,那就很诱人,但是使用较旧的方法. (19认同)
  • 注意:没有记录在任何地方,但"`<MajorUpgrade>`"元素必须放在*`<Package>`之后.否则,`candle`会出现以下错误:"错误CNDL0107:架构验证失败,第1行第473行出现以下错误:命名空间中的元素'Product'http://schemas.microsoft.com/wix/2006/ wi'在命名空间'http://schemas.microsoft.com/wix/2006/wi'中有无效的子元素'MajorUpgrade'.预期的可能元素列表:'包'." (16认同)
  • Bob Arnson的[博客文章](http://www.joyofsetup.com/2010/01/16/major-upgrades-now-easier-than-ever/)关于此提供了很多很好的信息. (8认同)
  • 只是想指出你不需要指定`AllowDowngrades`或`AllowSameVersionUpgrades`.他们默认不是. (4认同)
  • 我之前的评论是错误的 - 忽略它。我所描述的在安装时没有抱怨,它没有像我想象的那样升级。在“产品 ID”中添加星号。在“产品升级代码”中放置一个实际的 GUID - 永远不要改变它。在“Package Id”中放置一个星号。最后,当您增加“产品版本”中的数字时,它会进行实际更新。 (2认同)

Rob*_*ing 88

以下是我用于主要升级的语法:

<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>
Run Code Online (Sandbox Code Playgroud)

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

  • 好的,我刚刚在[这个答案](http://stackoverflow.com/a/3575801/6884)找到[MajorUpgrade元素](http://wix.sourceforge.net/manual-wix3/wix_xsd_majorupgrade.htm)完全符合我的要求,包括防止降级. (4认同)
  • 我从未明确安排InstallExecute. (3认同)
  • 我正在阅读Nick Ramirez在Wix上的书中的"升级和补丁"部分,他说如果你在InstallInitialize之后安排RemoveExistingProducts,那么你还必须安排`<InstallExecute After ="RemoveExistingProducts"/>`.你的例子没有这个 - 这是否意味着这本书是错的? (2认同)

Bri*_*pie 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>
Run Code Online (Sandbox Code Playgroud)

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

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

<InstallExecuteSequence>
  <RemoveExistingProducts After="InstallFinalize"></RemoveExistingProducts>
</InstallExecuteSequence>
Run Code Online (Sandbox Code Playgroud)

这将保留产品的先前版本,直到复制新文件和注册表项为止.这使我可以将数据从旧版本迁移到新版本(例如,您已将用户首选项的存储从注册表切换到XML文件,但您希望礼貌并迁移其设置).此迁移在InstallFinalize之前的延迟自定义操作中完成.

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

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

  • @Brian Gillespie:“...如果有未更改的文件...”是什么意思?Windows Installer 决定何时替换文件、AssemblyVersion、AssemblyFileVersion、文件大小等的标准是什么? (2认同)
  • @donttellya +1 以艰难的方式学会了这一点。`RemoveExistingProducts` 被安排在 `InstallFinalize` 之后,并且 dll 没有更新,因为 assemblyVersion 没有改变,但是像 AssemblyProduct 这样的其他字段是。我不想受文件比较例程的支配 - 我只想让以前的应用程序消失 (2认同)

Mik*_*ick 15

您可能最好在WiX用户邮件列表中询问此问题.

WiX最适合用于对Windows Installer正在做的事情的深入了解.您可能会考虑获取" Windows Installer的权威指南 ".

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

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

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

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

  • 毫无疑问迈克确切地知道他正在谈论什么,所有应有的尊重,但它让我感到绝望,因为对Windows安装程序正在做的事情有一个坚定的理解,所以想到让我的思绪混乱.在我了解它之前,我将在企业客户面前,在神奇的科技中心城镇进行Java和.NET咨询工作,超越环路,填写我的TPS报告,并想知道为什么生活看起来如此空洞.我认为我的下一个项目可能会安装NSIS,尽管它有所有缺点,就像一个荒谬的汇编式语言,它并没有让我理解Windows Installer正在做什么. (21认同)
  • @Tartley-与InnoSetup一起使用,它将为您节省类似于汇编的语言:)确保您也掌握了IStool,这对您有很大帮助。另外-同意对于简单安装来说,所有这些都太复杂了,但是我认为他们确实需要这种复杂性来安装SQL Server 2008之类的东西... (2认同)

Che*_*rra 11

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

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

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

正如Mike在Apress的书中所说的那样,"Windows安装程序的权威指南",它将帮助您理解,但它不是使用WiX编写的.

另一个非常有用的网站就是这个:

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


Sas*_*sha 10

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

<MajorUpgrade Schedule="afterInstallInitialize"
        DowngradeErrorMessage="A later version of [ProductName] is already installed. Setup will now exit." 
        AllowDowngrades="no" />
Run Code Online (Sandbox Code Playgroud)

但问题的主要原因是文档说使用" REINSTALL = ALL REINSTALLMODE = vomus "参数进行次要和小型升级,但并未说这些参数对于主要升级是禁止的 - 它们只是停止工作.所以你不应该在主要升级时使用它们.


Far*_*raz 7

我建议看一下Alex Shevchuk的教程.他通过WiX解释了"重大升级",并在从MSI到WiX的第8部分 - 重大升级中有一个很好的动手实例.


Dan*_*itt 7

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

*小更新 意味着对一个或几个文件进行小的更改,其中更改不保证更改产品版本(major.minor.build).您也不必更改产品GUID.请注意,在创建与以前版本不同的新.msi文件时,始终必须更改包GUID.安装程序会跟踪已安装的程序,并在用户想要使用这些GUID更改或删除安装时查找它们.对不同的包使用相同的GUID会使安装程序混淆.

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

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

  • 包:Id类型:AutogenGuid描述:产品或合并模块的包代码GUID.编译产品时,不应设置此属性以允许为每个构建生成包代码.编译合并模块时,必须将此属性设置为modularization guid.----所以我们不需要关注包ID,对吧? (3认同)

Mer*_*ndo 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>
Run Code Online (Sandbox Code Playgroud)

请注意,PUT-GUID-HERE应与您在Product的UpgradeCode属性中定义的GUID相同.