是什么原因导致MSI更新无法更新安装程序中的组件?

时间:2011-01-14 21:41:07

标签: windows-installer installshield installshield-2010

(编辑:问题已更改。)

我有一个带有安装程序的产品,该安装程序是由InstallShield 2010构建的,并且所有帐户都显示安装正常,作为“新”安装。

我定期更改安装内容,因为我更新了这个或那个包含错误修复的组件等等。在那些时候,我尝试更改已更新的文件的元数据中的版本号,但有些组件无法实现。当然,他们总是会有最近的修改日期。我也在MSI数据中更改产品的版本号。但是,我每次都没有更改包裹代码。

当某些用户在我的产品已经存在的系统上运行安装程序时,系统会提示他们使用更新模式UI(“您想要更新吗?”等),安装程序似乎已完成。但是,更新的文件并不总是覆盖旧文件,直到之后运行“修复”安装,特别是如果版本号没有更改,并且现在有证据表明用“强制覆盖”标记组件的内容不要改变这种行为。

这里发生了什么?有什么方法可以得到更好的结果吗?每当我修改产品或更新组件时,包装代码是否需要更改? (编辑:每次构建版本时,包代码都在变化,因此这不是问题的原因。)

编辑:这是一个更新UI,但更新后的维护是实际完成所需安装的内容。

4 个答案:

答案 0 :(得分:3)

您当然应该在每个构建中更改PackageCode。事实上,默认情况下,InstallShield有一个构建设置就可以实现这一点。

事实上,MSDN帮助主题Package Codes说:

不相同的.msi文件不应具有相同的包代码。更改包代码非常重要,因为它是安装程序用于搜索和验证给定安装的正确包的主要标识符。如果在不更改软件包代码的情况下更改软件包,则如果安装程序仍可访问这些软件包,则安装程序可能不会使用较新的软件包。

这就是您获得维护UI体验而非升级体验的原因。

现在,一旦您开始这样做,您将不得不考虑下一步是否要支持次要升级,主要升级或补丁来为您的应用程序提供服务。在将安装程序投入生产之前,了解这一点并测试您的策略非常重要。

答案 1 :(得分:1)

根据不变的文件版本信息,安装程序正在做它应该做的事情。

理想情况下,每次更改文件时都会更新文件版本(对于完全包含版本信息的文件),但如果由于某种原因您不打算这样做,仍有几种方法可以强制组件更新。

简单的方法是设置REINSTALLMODE属性。您可以将其设置为“amus”,这将导致重新安装所有文件。请参阅MSDN - http://msdn.microsoft.com/en-us/library/aa371182%28v=vs.85%29.aspx

这有效,但可能会引入自己的问题。例如,如果您在程序包中包含一些可再发行组件,则强制重新安装这些可再发行组件可能会导致它们被反向。

允许您在单个组件级别进行控制的更难的方法是使用自定义操作。调用MsiSetComponentState以将每个组件显式设置为您想要的任何状态。 http://msdn.microsoft.com/en-us/library/aa370383%28v=VS.85%29.aspx

我的回忆是您的自定义操作必须在CostFinalize之后,因此安装程序不会消除您的更新。

答案 2 :(得分:1)

在@ ChristopherPainter上面的回答中,我也了解到InstallShield有一个设置来自动生成包代码,但他没有说出它的位置。所以对于其他寻找它的人来说:

此设置位于Media / Releases /(版本名称),产品配置,常规选项卡下。 在那里你会发现"生成包裹代码"并且您可以验证它是否设置为是。

答案 3 :(得分:0)

当Windows Installer决定是否安装组件时,它将首先查看“keypath”资源是否已存在。如果是,则不安装组件中的任何资源。 (我假设Installshield将每个文件放在它自己的组件中,并且keypath是文件。)

当密钥路径资源是版本化文件时,Windows Installer仅在找到具有相同或更高版本的文件时才会认为它存在。因此,如果已存在具有相同版本号的文件,则不会再次安装该文件。因此,在不更改版本号的情况下更改文件会导致问题。

编辑:至于修复解决问题的原因:我相信它会重新安装c:\windows\installer中缓存的MSI文件中的所有组件,而不管密钥路径资源的存在/版本。这似乎是合乎逻辑的,因为它是确保损坏的文件被还原的唯一方法。 (我无法立即在MSDN上找到明确的参考资料来支持这一点,抱歉。)

TortoiseSVN开发人员blogged在从1.6.10之前版本升级到更高版本时,会遇到TortoiseSVN中的类似问题。在他的情况下,问题不是文件的版本,而是一些组件的键路径的变化具有相同的结果。在这种情况下,修复也修复了应用程序。