我目前很难尝试使用根据此处的说明构建的 MST 在多实例场景中使用 MSP(也使用 WiX 构建)修补 MSI(使用 WiX 构建):
http://msdn.microsoft.com/en-us/library/windows/desktop/aa367797(v=vs.85).aspx
我构建的转换工具:
- 生成新的 UpgradeCode/ProductCode 属性
- 更新 Upgrade 表以使用新的 UpgradeCode
- 更新 ProductName 属性以包含实例名称
- 使用包含实例名称的新项目更新 ServiceControl 和 Shortcut 表
- 更新 Directory 表以更新包含 INSTALLDIR 行的实例名称的 DefaultDir 列
- 生成转换摘要信息并写入转换
安装应用了转换的 MSI 似乎可行。我这样调用 msiexec :
msiexec /i <product.msi> TRANSFORMS=<instance.mst> MSINEWINSTANCE=1
但是,修补似乎不起作用。我尝试按照此处所述应用补丁:
http://msdn.microsoft.com/en-us/library/windows/desktop/aa369528(v=vs.85).aspx
msiexec /p <mypatch.msp> /n {product-code}
安装程序立即退出并显示“Windows Installer 服务无法安装升级补丁,因为要升级的程序可能丢失,或者升级补丁可能会更新程序的不同版本”。
基本 MSI 已安装,并且已在 WiX 中的 PatchCreation 元素上使用 AllowProductCodeMismatches="yes" 构建补丁。
如何获得要安装的补丁?
编辑:进一步阅读后,看起来我在做一些不好的事情。我现在已停止更改 UpgradeCode 属性,因为它似乎不需要,而且我自己工具的实例转换要轻得多。
我还查看了 @YanSklyarenko 的博客条目以进行修补 - 他修改了现有补丁以更改补丁适用的 ProductCode。我试过用类似的代码做同样的事情:
// Copy original patch
File.Copy(_patchPath, _newPatchPath, true);
// Update patch target product code
using (var patch = new PatchPackage(_patchPath))
using (var patchForWrite = new Database(_newPatchPath, DatabaseOpenMode.Transact))
{
var originalProductCode = patch.GetTargetProductCodes().First();
var productCode = _newProductCode;
foreach (var transform in patch.GetTransforms())
{
// Extract/update transforms
var tempFileName = Path.GetTempFileName();
var transformFileName = transform + _instanceName;
patch.ExtractTransform(transform, tempFileName);
using (var summaryInfo = new SummaryInfo(tempFileName, true))
{
summaryInfo.RevisionNumber = summaryInfo.RevisionNumber.Replace(originalProductCode, productCodeString);
summaryInfo.Persist();
}
// Write transform to new patch
using (var insertView = patchForWrite.OpenView("INSERT INTO `_Storages` (`Name`,`Data`) VALUES ('{0}', ?)", transformFileName))
{
using (var record = new Record(1))
{
record.SetStream(1, new FileStream(tempFileName, FileMode.Open));
insertView.Execute(record);
patchForWrite.Commit();
}
}
// Add transform to patch properties
patchForWrite.SummaryInfo.LastSavedBy += ";:" + transformFileName;
}
// Update patch properties
patchForWrite.SummaryInfo.Template = patchForWrite.SummaryInfo.Template.Replace(originalProductCode, productCodeString);
patchForWrite.SummaryInfo.Persist();
}
我安装补丁仍然没有任何运气,并且 msiexec 在写入任何日志之前仍然退出。
编辑2:我仍然没有运气。我试过使用 WiX 实例转换来安装,但补丁仍然不适用。我的 PatchCreation 元素定义了每个实例的 TargetProductCode 元素,并且 AllowProductCodeMismatches 仍然打开。
编辑 3:听起来 AllowProductCodeMismatches 是一个 MSIMSP 东西,允许在两个不同的产品代码之间跳转以创建补丁而不是验证。目标产品代码必须包含在补丁中。不幸的是,对我来说 TargetProductCode 元素似乎被忽略了。
我在这里不是一个 100% 肯定的人,但我认为一些验证与基于两个图像的补丁生成有关,而不是补丁应用程序本身(以老式的方式使用 PCP 的 MSIMSP 生成补丁)文件)。如果在补丁变换生成中使用的两个图像没有相同的产品代码并且 ProductID 验证设置为 no,那么您将不会收到错误。否则,在补丁生成过程中会返回一个错误,让您知道您的输入可能无效等