在MajorUpgrade中降级文件

时间:2015-05-21 15:06:44

标签: wix windows-installer burn wix3.8

修改 请看底部的小repro。

我遇到与此相同的问题:Windows installer deletes versioned file during product upgrade, instead of downgrading it

File Table |File                                            | Component_                                   | FileName    | FileSize | Version|
-----------|--------------------------------------------------------------------------------------------------------------------------------------------
old MSI    |fileEcMWtDjRdBXxvVHY.WvW_XXJI4GZcq5iAszC_F3KIwk | Cj9pc73bMjDSVVGUqS81_nPSltSFuUEweshtzct2AHi4 | bftlang.dll | 118784   | 2004.553.4453.1067
new MSI    |fileYXlC3cFPRwh6qrJ5u..Ll052XUiMylAmA6a4BwMlz_o | CZJsalkL4nX.r6JS5xXH3pjmr9mY1AO4CITmUEHjP82I | bftlang.dll | 118784   | 2004.553.4453.1064

Component Table |Component                                    | ComponentId                            | KeyPath
----------------|---------------------------------------------------------------------------------------------------------------------------------------
old MSI         |Cj9pc73bMjDSVVGUqS81_nPSltSFuUEweshtzct2AHi4 | {C45097D5-E359-48B5-9F85-AB5EC81D62BF} | filepcu3NI3UMnsXucCthGSqTSHMvUoyVuyQHRbEXnUVii0
new MSI         |CZJsalkL4nX.r6JS5xXH3pjmr9mY1AO4CITmUEHjP82I | {8B97BC16-7D4D-45CD-A3E3-903C60868202} | fileYXlC3cFPRwh6qrJ5u..Ll052XUiMylAmA6a4BwMlz_o


MSI (s) (88:A0) [20:12:50:115]: Disallowing installation of component: {8B97BC16-7D4D-45CD-A3E3-903C60868202} since the same component with higher versioned keyfile exists

(关于主题:Stackoverflow降价支持表吗?help中没有提到它们。)

出于某种原因,我们的增量构建系统会创建有时会减少的虚假版本号。虽然我同意如果你先告诉我解决这个问题,但它不在我的控制范围内,如果有人想要这样做,同样的问题就会显现出来。降级nuget包。

链接问题中提到的解决方法(在成本计算之前安排它)解决了原始问题,但它似乎会导致刻录和升级问题。

提到的另一个解决方法是更改​​REINSTALLMODE,但我正在使用Burn,afaik不允许我更改它。 (我们没有共享组件,所以如果可以更改REINSTALLMODE,那可能是最好的解决方案。)

在成本核算之前安排它之后,我有几次观察到引导程序在ARP中注册的问题,但是MSI没有安装。 (我认为这是因为取消升级导致新安装回滚但没有重新安装旧版本 - 但我不确定)。

我们通过调用Guid.NewGuid()生成组件GUID,因此违反了组件规则,因此我无法在InstallFinalize之后安排它,但是注释提到MSI然后保留旧的(更高版本的)版本,这绝对不是我想要的。

基本上,我在MSI中有一个目录布局,并希望将1:1复制到所选目录中,忽略并覆盖任何现有文件,无论其版本如何。为了解决非版本化文件的类似问题,我将此模式用于每个文件:

<Component Directory="APPLICATIONFOLDER" Permanent="no" Guid="##Guid.NewGuid()##" Id="##some random id##">
    <File Id="##some different random id##" Source="#source#" />
    <RemoveFile Id='##some other random id##' On='install' Name='#name#'/>
</Component>

如果可能,我想在InstallInitialize之后安排RemoveExistingProducts,这样卸载就在事务中。

在重大升级过程中有没有一种干净的方法来降级文件?即使在成本计算之前安排它的工作方式大多有效,我仍然不得不压制ICE27,它抱怨它。

修改
我搜索了一下,发现this question提到在编译后修改文件表。我想这对我来说可能是一个可行的选择,但是能解决一个msi错误真的很难吗? (我认为是删除文件的主要升级而不是将其替换为错误。)

EDIT2:

我创建了一个小型repro,它包含6个MSI文件:

    with_different_guids
  • ,DLL被降级,但两个版本具有不同的ID和不同的GUID。
  • with_same_guids 中,DLL也会降级,但两个版本都具有相同的(自动生成的)ID和GUID。

两者都表现出相同的行为:

如果我安装1 \ SetupProject.msi,该目录包含三个文件,1 .txt,1 .dll和1.exe。
如果我然后运行2 \ SetupProject.msi,只重新安装.txt和.exe(.exe的版本不变)。

rep_before_costinitialize 中,REP在CostInitialize之前进行调度,而MajorUpgrade正常工作,所有三个文件都在磁盘上。

EDIT3:
我也能够重现我的烧伤问题:
如果我在CostInitialize之前安排REP,则MajorUpgrade按预期工作:DLL被降级 但是Burn Upgrade的事务逻辑不再按预期工作 如果我安装 setupExe \ 1 \ BootstrapperProject.exe ,则启动 setupExe \ 2 \ BootstrapperProject.exe ,但在中间取消它,既没有安装MSI,也没有安装 1 仍显示在ARP中。

Repro:https://onedrive.live.com/redir?resid=5062efe7e0c8eccc!124918&authkey=!ANYtHc5SkzFXn5U&ithint=file%2czip

1 个答案:

答案 0 :(得分:1)

FWIW,过去我曾经和MS支持过关于使用REP之前成功进行升级的工作,当时他们说没关系,同时指出它也在MigrateExistingFeatures之前,所以如果你在迁移期间迁移功能升级就会出现问题。

我不会改变File表。这可以保证磁盘上的版本与File表中的版本不匹配,并使该文件成为修复的候选对象。如果磁盘上的版本是2.0并且File表中的版本是3.0,则修复将看到该文件已损坏。在决定是否需要修补或升级文件之前,一些主要的升级或补丁会注意到差异,并要求您提供源MSI以恢复文件(因为版本不匹配)。如果磁盘上的版本与File表不匹配,Windows无法知道传入更新是否需要更新文件。

在任何情况下,对于单个文件,使用Visual Studio打开darn文件并更改真实版本会更安全,更容易!

还有偶然的错误,如https://support.microsoft.com/en-us/kb/905238,这会使问题黯然失色。

您是否使用您的代码生成该File表键?我怀疑你的File表键在不同的MSI中是不同的。这可能不是问题,但已知更改File表密钥会导致其他更新方案出现问题。如果升级尝试使用文件表的主键(关系数据库执行)找到文件的先前版本,并且无法在较旧的MSI中找到它,则结果可能无法预测。