【发布时间】:2013-02-11 14:25:03
【问题描述】:
我目前在尝试使用根据此处的说明构建的 MST 在多实例场景中使用 MSP(也使用 WiX 构建)修补 MSI(使用 WiX 构建)时遇到困难:
http://msdn.microsoft.com/en-us/library/windows/desktop/aa367797(v=vs.85).aspx
我构建的转换工具:
- 生成新的 UpgradeCode/ProductCode 属性
- 更新升级表以使用新的 UpgradeCode
- 更新 ProductName 属性以包含实例名称
- 使用包含实例名称的新项目更新 ServiceControl 和快捷方式表
- 更新目录表以更新包含 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,那么您将不会收到错误。否则,在补丁生成过程中会返回一个错误,让您知道您的输入可能无效等
【问题讨论】:
-
前段时间我发表了一篇关于如何使用 WiX 实现类似功能的文章:ysdevlog.blogspot.com/2011/08/revisited-multiple-instance.html。您可能想尝试一下。
-
是的,在我自己解决之后,我写了那篇文章来分享我的经验:)
-
干杯 @YanSklyarenko - 从 WiX 邮件列表中看起来你过去遇到过同样的问题。但是,您使用的是纯 WiX 补丁设置 - 我正在尝试使用补丁创建属性。我原以为 PatchCreation AllowProductCodeMistmatches="yes" 会解决问题,但我仍然收到错误消息。我还有什么需要做的吗?
-
例如,在您第一次尝试此操作时,您编写了代码以使用目标产品代码更新补丁。如果我最初针对不同的产品代码构建了补丁,我需要为实例更新它吗?
标签: wix windows-installer