【问题标题】:Install a file regardless of version number with WiX使用 WiX 安装文件,无论版本号如何
【发布时间】:2020-03-09 20:55:23
【问题描述】:

MyApp 1.0 版包含文件 foo.dll。该文件的版本是 10.5.567。现在MyApp是2.0版本,foo.dll的版本是2.0.123。版本低于旧版本。编写此 dll 的供应商决定使用文件版本号向后退。这不是我可以改变的决定。

如何让 WiX 始终安装此文件?

RemoveExistingProducts 操作安排在 InstallFinalize 操作之后,也无法更改。

InstallShield 有一个“始终覆盖”标志,但我认为如果不通过编译器开关更改所有文件的行为,我就无法模仿这一点。我不想要这个。我只想更新这个文件。

我也试过

<RemoveFile Id="foo.dll" On="install" Name="foo.dll" />

但这也不起作用。稍后我最终得到“错误 2753 文件 foo.dll 未标记为安装”。

【问题讨论】:

    标签: wix windows-installer


    【解决方案1】:

    这个帖子已经有 10 年历史了,我们也有这个问题,真是太疯狂了。其他方法对我们不起作用。

    如何解决:

    1. 无论版本如何,应复制的所有文件都必须位于它们自己的组件中
    2. Component 元素必须具有唯一的 Guid,而不是 *
    3. 在内部File 元素中将KeyPath 设置为no

    例子:

    <Component Id="cmpExample" Guid="{5ABE7229-C247-4CBA-B8DE-2C4968CD103E}" >
         <File Id="fileExample" KeyPath="no" Source="$(var.TargetDir)\SomeExample.dll" />
    </Component>
    

    我建议将所有这些component 元素聚合到一个组件组中。此外,如果您使用heat.exe 收集所有文件,则可以使用XML Transformation 删除这些文件。

    使用此解决方案,您可以复制文件,即使安装的文件版本更高。当您在升级时安装更高版本的文件时,它仍然可以正常工作。

    【讨论】:

    • 我按照 XML 转换中的建议尝试了这个。在构建基本安装程序时,我能够将多个组件的 KeyPath 设置为“否”。但是在构建补丁安装程序时我遇到了错误,因为它使用'*'代替了 guid。文件是否需要在基础和补丁中都用 KeyPath='no' 标记?如果是这样,在为补丁收集文件时,我还可以在 heat 命令上使用 -gg 选项吗?
    • 好的,我知道在生成补丁时我不能在 heat 命令上使用 -gg,因为这会违反你的第 2 点。此外,当我尝试在基础上使用 KeyPath='no',但在补丁上使用 KeyPath='yes' 时,它不起作用。因此,我们似乎无法在 WiX 补丁中“安装文件而不管版本号”......只能在基本安装程序中。
    【解决方案2】:

    这并不容易,因为它违反了 MSI 包的标准行为。编译时,您必须在 light.exe 中使用 -sf 设置 supress-file-options。然后读取的文件中没有文件信息。您可以设置 DefaultVersion 将使用此版本。 我也在解决方案中使用了RemoveFile,但我可以说它有效。我已将它添加到我添加文件的同一组件中。

       <Component>
            <File DiskId="1" Id="fooDLL" Name="foo.dll" Vital="yes" 
             DefaultVersion="$(var.MAJORVERSION).$(var.MINORVERSION).$(var.BUILDVERSION)" 
             DefaultLanguage="0"></File>
            <RemoveFile Id='RemoveOldDLL' On='install' Name='foo.dll'/>
       </Componente>
    

    这不是一个干净的方法,但删除旧版本对我有用。

    【讨论】:

    • 没试过这个,但看起来可行。有关不同方法列表的链接,请参阅我在此线程中的回复。
    • 我尝试使用 DefaultVersion 安装一个 .MDE 文件,当我安装补丁时它运行良好,文件被正确覆盖。唯一的问题是补丁无法卸载。安装日志说“新文件版本化 - 现有文件未版本化”,卸载需要原始媒体。我还没有解决这个问题,所以欢迎任何建议。
    【解决方案3】:

    不久前我回答了一个类似的问题: Forcing an upgrade of a file that is modified during its initial installation

    我想我会使用一个配套文件来解决这个问题,但是你可能会遇到验证错误,因为有问题的文件是一个 dll,因此被认为是一个可执行文件。我相信它仍然可以工作,而且可靠。

    【讨论】:

      【解决方案4】:

      注释

      使用“InstallShield 技巧”强制始终覆盖 Light.exe 输出:

      XPath="/wixOutput/table[@name='File']/row/field[5]" InnerText=„65535.0.0.0“

      【讨论】:

      • 我认为这与在&lt;File /&gt; 元素上设置DefaultVersion="65535.0.0.0" 相同。但我相信这也有它自己的局限性。
      【解决方案5】:

      值得尝试的一件事是在序列的早期将 RemoveExistingProducts 设置为真实。然后 MSI 应首先删除旧程序,然后安装升级。这将解决您的问题。例如

      <InstallExecuteSequence>
          <RemoveExistingProducts After="CostFinalize" />
      </InstallExecuteSequence>
      

      【讨论】:

      • 遗憾的是,它必须发生在之前 CostFinalize(因为 CostFinalize 是 MSI 评估要更新哪些文件的步骤)——据我所知,RemoveExistingProducts 不是允许这么早进行测序。如果您找到解决方法,我很乐意听到它。 :)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多