在卸载时跳过自定义操作(WiX)

时间:2017-06-26 16:48:15

标签: wix windows-installer

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

新安装程序中是否有任何方法告诉WiX在卸载时跳过该特定自定义操作?

2 个答案:

答案 0 :(得分:1)

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

解决方案:

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

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

  

msiexec.exe / fv"< path_to_MSI>"

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

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

答案 1 :(得分:0)

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

第一部分仍然正确。您必须在wix项目中解决该问题,并使用相同的ProductCode / Version并仅使用MSI数据库生成一个新软件包。我们将使用此软件包重新缓存前一个软件包,以便可以成功将其卸载。

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

  1. 恢复以前的msi
  2. 启动新的msi(产品更新)

我发现的唯一方法是创建一个Wix捆绑包以按顺序将这两个步骤链接在一起。

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。