【问题标题】:Skip custom action on uninstall (WiX)在卸载时跳过自定义操作 (WiX)
【发布时间】:2017-11-29 13:59:15
【问题描述】:

我正在为现有产品创作 MSI。在以前的版本中,有一个自定义操作不限于仅在安装时运行,现在在卸载时会失败 w/ MajorUpgrade。

新安装程序中有什么方法可以告诉 WiX 在卸载时跳过特定的自定义操作吗?

【问题讨论】:

  • 不幸的是,old 卸载程序已执行,但 AFAIK 您可以在主要升级之前先 patch 前一个。

标签: wix windows-installer


【解决方案1】:

是的,您可以通过新安装程序自动执行此操作。

解决办法:

1) 您需要解决构建当前安装程序版本的项目中的问题,并从该项目再次构建 good MSI。在这种情况下,您只需要 MSI 数据库,通常为几 KB,not the entire setup package(即包含所有安装文件等的 CAB 文件...)

2) 在新的安装程序中,您需要在 RemoveExistingProducts 标准操作之前运行的自定义操作,该操作将重新缓存计算机上先前版本的 MSI。您的自定义操作必须执行此命令:

msiexec.exe /fv ""

您尝试重新缓存的 MSI 是您在第 1 步中构建的新 MSI。您需要将此 MSI 作为资源包含在新版本安装程序(以及未来版本,以防某些用户跳过此版本)中,并将提取此 MSI 文件的完整路径作为参数传递给您的自定义操作。

基本上,您要做的是使用正确的 MSI 自动执行重新缓存旧安装的步骤(您在自定义操作中设置了正确的条件)。现在,当 RemoveExistingProducts 标准操作将执行时,Windows Installer 将使用新缓存的 MSI 触发旧版本的卸载,该 MSI 在您的自定义操作上设置了正确的条件,并成功卸载。

【讨论】:

  • 这很好用,但您必须确保 ProductCode 相同(并且可能是版本)。如果您有 ProductID="*",请在注册表中查找 ProductCode(例如,HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall)并找到它,然后暂时将 * 更改为它。
【解决方案2】:

Bodgan Mitrache 接受的答案似乎并不完全有效,因为无法从另一个 msi 包运行 msiexec 命令。

第一部分仍然是正确的。您必须解决 wix 项目中的问题并生成具有相同 ProductCode/Version 且仅使用 MSI 数据库的新包。我们将使用这个包重新缓存之前的包,以便成功卸载它。

在新的安装程序中,您需要 2 个步骤:

  1. 重新缓存上一个 msi
  2. 推出新的微星(产品更新)

我发现的唯一方法是创建一个 Wix 包以按顺序链接 2 个步骤。

1- 可以通过一个独立的可执行文件进行重新缓存操作,该可执行文件包括对 msiexec /fv valid_recache.msi 的简单调用。这是一个 C++ 示例:

#include <Windows.h>

int main()
{
    CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);

    SHELLEXECUTEINFO shExecInfo;
    shExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
    shExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_UNICODE;
    shExecInfo.hwnd = NULL;
    shExecInfo.lpVerb = L"open";
    shExecInfo.lpFile = L"cmd";
    shExecInfo.lpParameters = L"/c msiexec /fv path_to\\recache.msi";
    shExecInfo.lpDirectory = NULL;
    shExecInfo.nShow = SW_SHOW;
    shExecInfo.hInstApp = NULL;
    ShellExecuteEx(&shExecInfo);
    WaitForSingleObject(shExecInfo.hProcess, INFINITE);
}

2- 像往常一样从您的项目创建新的 msi(使用新的 ProductCode 和更高的版本号)

在一个看起来像这样的 Wix 捆绑项目中结合这两个步骤(有用的链接 here):

<?xml version="1.0" encoding="UTF-8"?>
<Wix 
  xmlns="http://schemas.microsoft.com/wix/2006/wi"
  xmlns:bal="http://schemas.microsoft.com/wix/BalExtension"
  xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">

  <Bundle 
    Name="your_name" 
    Version="1.0.0" 
    Manufacturer="your_organization" 
    UpgradeCode="your_uuid" 
    Copyright="your_copyright" 
    AboutUrl="your_url">

    <BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.HyperlinkLargeLicense">
      <bal:WixStandardBootstrapperApplication
        LicenseUrl=""
        LogoFile="your_logo"
        ShowVersion="yes"
        SuppressOptionsUI="yes"/>
    </BootstrapperApplicationRef>

    <!--Do registry search to find the current msi package version-->
    <util:RegistrySearch 
      Root="HKLM" 
      Key="SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{ProductCode}"
      Value="Version"
      Variable="CurrentMsiPackageVersion"
      Result="value" 
      Win64="yes" />

    <Chain>
      <!--Do recaching only if the current version is the invalid one-->
      <ExePackage 
          Id="Patch" 
          SourceFile="MsiRecache.exe"
          Vital="yes"
          InstallCondition="(CurrentMsiPackageVersion="invalid_msi_version")">

          <Payload Name="recache.msi" SourceFile="relative_path_to\recache.msi"/>
      </ExePackage>

      <!--Launch new installation-->
      <MsiPackage 
        Id="your_id"
        SourceFile="your_setup.msi"
        DisplayInternalUI="yes"
        Vital="yes"/>
    </Chain>
  </Bundle>
</Wix>

最后,通过调用生成包:

candle.exe -ext WixBalExtension -ext WixUtilExtension bundle.wxs

light.exe -ext WixBalExtension -ext WixUtilExtension bundle.wixobj

请注意,该包将具有 .exe 扩展名而不是 msi。

【讨论】:

    猜你喜欢
    • 2013-03-08
    • 1970-01-01
    • 1970-01-01
    • 2012-03-21
    • 1970-01-01
    • 2010-09-24
    • 2011-08-10
    • 2011-03-02
    • 1970-01-01
    相关资源
    最近更新 更多