带补丁的 MSI 多实例安装
Posted
技术标签:
【中文标题】带补丁的 MSI 多实例安装【英文标题】:MSI multi-instance installation with patches 【发布时间】: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 元素似乎被忽略了。
http://windows-installer-xml-wix-toolset.687559.n2.nabble.com/Re-Multiple-instance-patches-td1559146.html
我在这里不是一个 100% 肯定的人,但我认为一些验证与基于两个图像生成补丁有关,而不是补丁应用程序本身(以老式的方式生成补丁)来自 PCP 文件的 MSIMSP)。如果在补丁变换生成中使用的两个图像没有相同的产品代码并且 ProductID 验证设置为 no,那么您将不会收到错误。否则,在补丁生成过程中会返回一个错误,让您知道您的输入可能无效等
【问题讨论】:
前段时间我发表了一篇关于如何使用 WiX 实现类似功能的文章:ysdevlog.blogspot.com/2011/08/revisited-multiple-instance.html。您可能想尝试一下。 是的,在我自己解决之后,我写了那篇文章来分享我的经验:) 干杯 @YanSklyarenko - 从 WiX 邮件列表中看起来你过去遇到过同样的问题。但是,您使用的是纯 WiX 补丁设置 - 我正在尝试使用补丁创建属性。我原以为 PatchCreation AllowProductCodeMistmatches="yes" 会解决问题,但我仍然收到错误消息。我还有什么需要做的吗? 例如,在您第一次尝试此操作时,您编写了代码以使用目标产品代码更新补丁。如果我最初针对不同的产品代码构建了补丁,我需要为实例更新它吗? 【参考方案1】:创建补丁涉及遵循多个规则,而不仅仅是匹配产品代码。以下 MSDN 文章更详细地解释了这些规则:http://msdn.microsoft.com/en-us/library/aa367850.aspx
你也可以在 Yan Sklyarenko 链接的文章中看到,同样的规则在一开始也给他带来了问题。
【讨论】:
我们的补丁可以正常安装。但是由于我们更改了多实例安装的产品代码,我很难让 Windows Installer 允许针对不同的产品代码安装补丁。我认为添加 AllowProductCodeMistmatches="yes" 就足够了 - 但似乎不是。【参考方案2】:我已经设法让它工作了。出于各种原因,我们的原始补丁是使用 PatchCreation 元素创建的。以这种方式创建的转换设置了检查 ProductCode 和 UpgradeCode 的验证。最后,我更新了我的转换以将其关闭,而不是更改每个转换的 ProductCode/UpgradeCode。所以总而言之,使补丁适用于新产品代码:
更新模板 SummaryInfo 属性并将原始 ProductCode 替换为实例 ProductCode 提取转换并将其替换为禁用 ProductCode 和 UpgradeCode 验证的版本然后安装补丁:
REM This works fine
msiexec /p <patch.msp> /n <ProductCode>
这没有对我有用 - 我从日志中收到一条错误消息,指出 Windows Installer 无法创建补丁的临时副本。:
REM DON'T USE THIS!
msiexec /i <ProductCode> PATCH=<patch.msp>
编辑:要禁用的适当验证标志是:
PatchProduct = 0x00020000, // Disables product code matches
PatchUpgradeCode = 0x08000000, // Disables upgrade code matches
PatchMagic = 0x00040000, // Heck knows what this does - but Orca disables this
【讨论】:
以上是关于带补丁的 MSI 多实例安装的主要内容,如果未能解决你的问题,请参考以下文章
开发人员学Linux:CentOS7编译安装MySQL5.17.8多实例及主从复制