【发布时间】:2017-11-29 13:59:15
【问题描述】:
我正在为现有产品创作 MSI。在以前的版本中,有一个自定义操作不限于仅在安装时运行,现在在卸载时会失败 w/ MajorUpgrade。
新安装程序中有什么方法可以告诉 WiX 在卸载时跳过特定的自定义操作吗?
【问题讨论】:
-
不幸的是,old 卸载程序已执行,但 AFAIK 您可以在主要升级之前先 patch 前一个。
标签: wix windows-installer
我正在为现有产品创作 MSI。在以前的版本中,有一个自定义操作不限于仅在安装时运行,现在在卸载时会失败 w/ MajorUpgrade。
新安装程序中有什么方法可以告诉 WiX 在卸载时跳过特定的自定义操作吗?
【问题讨论】:
标签: wix windows-installer
是的,您可以通过新安装程序自动执行此操作。
解决办法:
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 在您的自定义操作上设置了正确的条件,并成功卸载。
【讨论】:
Bodgan Mitrache 接受的答案似乎并不完全有效,因为无法从另一个 msi 包运行 msiexec 命令。
第一部分仍然是正确的。您必须解决 wix 项目中的问题并生成具有相同 ProductCode/Version 且仅使用 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。
【讨论】: