我正在为现有产品创作MSI。在以前的版本中,有一个自定义操作不限于仅在安装时运行,现在在卸载w / MajorUpgrade时失败。
新安装程序中是否有任何方法告诉WiX在卸载时跳过该特定自定义操作?
答案 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个步骤:
我发现的唯一方法是创建一个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。