带补丁的MSI多实例安装

时间:2013-02-11 14:25:03

标签: wix windows-installer

我目前在使用根据此处的说明构建的MST在多实例方案中尝试使用MSP(也使用WiX构建)修补MSI(使用WiX构建)时遇到困难:

http://msdn.microsoft.com/en-us/library/windows/desktop/aa367797(v=vs.85).aspx

我构建的转换工具:

  • 生成新的UpgradeCode / ProductCode属性
  • 更新升级表以使用新的UpgradeCode
  • 更新ProductName属性以包含实例名称
  • 使用包含实例名称
  • 的新项更新ServiceControl和快捷方式表
  • 更新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元素。

http://windows-installer-xml-wix-toolset.687559.n2.nabble.com/Re-Multiple-instance-patches-td1559146.html

  

我不是100%肯定的,但我认为一些验证与基于两个图像的补丁的生成有关,而不是补丁应用程序本身(在旧学校中使用补丁的方式)来自PCP文件的MSIMSP)。如果修补程序转换生成中使用的两个图像没有相同的产品代码且ProductID验证设置为no,那么您将不会收到错误。否则,在修补程序生成期间会返回错误,告知您输入可能无效等等

2 个答案:

答案 0 :(得分:0)

创建补丁涉及遵循多个规则,而不仅仅是匹配产品代码。以下MSDN文章详细介绍了这些规则:http://msdn.microsoft.com/en-us/library/aa367850.aspx

正如你在Yan Sklyarenko所链接的文章中所做的那样,同样的规则也在一开始就给他带来了问题。

答案 1 :(得分:0)

我设法让这个工作。由于各种原因,我们使用PatchCreation元素创建了原始补丁。以这种方式创建的转换是通过验证来设置的,该验证检查ProductCode和UpgradeCode。最后,我更新了我的转换以关闭它,而不是为每个转换更改ProductCode / UpgradeCode。总而言之,要使补丁适用于新的产品代码:

  • 更新Template 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