多实例理解WIX的PackageCode、ProductCode和UpgradeCode

Understanding PackageCode, ProductCode and UpgradeCode of WIX with multi instances

只有当我使用相同的 msi 文件时,我的多实例 msi 设置才有效。那么用户

如果我使用新版本的设置和 运行 更新,那么

阅读后关注博文 http://blogs.msdn.com/b/pusu/archive/2009/06/10/understanding-msi.aspx

我硬编码了 PackageCode、ProductCode(每个实例)和 升级代码。它按预期工作。但是我收到一个很大的警告 建造。我可以忽略这个吗?这是正确的解决方案吗?

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">
    <Product Id="*" Language="1033" Manufacturer="i-net software GmbH" Name="i-net Test"
        UpgradeCode="02c7fa01-5143-38ed-b923-2c2aaff301ae" Version="8.0.0.507">
        <Package Comments="i-net Test Server" Compressed="yes" Id="c748d2f0-9ca5-3cbc-be9a-730c6d621f00"
            InstallScope="perUser" />
        <Media Cabinet="media1.cab" EmbedCab="yes" Id="1" />
        <InstanceTransforms Property="INSTANCE_ID">
            <Instance Id="Instance_0" ProductCode="c748d2f0-9ca5-3cbc-be9a-730c6d621f00" UpgradeCode="c748d2f0-9ca5-3cbc-be9a-730c6d621ff3" />
            <Instance Id="Instance_1" ProductCode="c748d2f0-9ca5-3cbc-be9a-730c6d621f01" UpgradeCode="4c8e1670-9d04-3dce-b88a-1a4dbbbc976d" />
            <Instance Id="Instance_2" ProductCode="c748d2f0-9ca5-3cbc-be9a-730c6d621f02" UpgradeCode="b76f160d-9395-3eda-a13d-d0566379ca8f" />
        </InstanceTransforms>
        <MajorUpgrade AllowDowngrades="yes" />
        <Directory Id="TARGETDIR" Name="SourceDir">
            <Directory Id="ProgramFilesFolder">
                <Directory Id="INSTALLDIR" Name="i-net Test" />
            </Directory>
        </Directory>
        <DirectoryRef Id="INSTALLDIR">
            <Directory Id="Server" Name="Server">
                <Component Guid="d62d7bcb-9242-39da-a43a-015df0f965af" Id="Server_Comp" MultiInstance="yes">
                    <CreateFolder />
                    <File Id="Server_testBuilds.jar" Name="testBuilds.jar" Source="..\testBuilds.jar" />
                </Component>
            </Directory>
            <Component Guid="1543477d-59fc-3ec3-bb67-a541abd9cfba" Id="instance_path" MultiInstance="yes">
                <RegistryKey ForceDeleteOnUninstall="yes" Id="instance_path_reg"
                    Key="Software\i-net software GmbH\i-net Test\Instances\[INSTANCE_NUMBER]" Root="HKLM">
                    <RegistryValue Type="string" Value="[INSTALLDIR]" />
                </RegistryKey>
            </Component>
        </DirectoryRef>
        <Property Id="INSTANCE_ID" Value="NotSet" />
        <Property Id="InstancesCount" Value="3" />
        <CustomAction Id="SetInstanceID" Script="vbscript">...</CustomAction>
        <InstallUISequence>
            <Custom Action="SetInstanceID" Before="ExecuteAction" />
            <Custom Action="SetTransforms" After="SetInstanceID">ACTION = "INSTALL"</Custom>
        </InstallUISequence>
        <InstallExecuteSequence>
            <Custom Action="SetInstanceID" Before="ValidateProductID" />
            <Custom Action="SetProductName" After="SetInstanceID">PRODUCT_NAME</Custom>
        </InstallExecuteSequence>
        <CustomAction Id="SetTransforms" Property="TRANSFORMS" Value="{:[INSTANCE_ID];}[TRANSFORMS]" />
        <CustomAction Id="SetProductName" Property="ProductName" Value="[PRODUCT_NAME]" />
        <Feature Id="MainApplication">
            <ComponentRef Id="Server_Comp" />
            <ComponentRef Id="instance_path" />
        </Feature>
    </Product>
</Wix>

您可以在 https://github.com/i-net-software/SetupBuilder/blob/master/src/com/inet/gradle/setup/msi/MultiInstance.vbs

找到 SetInstanceID 操作

在我为 ProductCode(全局和每个实例)使用“*”之前 仅硬编码了 UpgradeCode(全局和每个实例)。

解错了。必须为每个构建更改 PackageCode 和 ProductCode。否则更新无法正常工作。这对单个实例有效,但对多个实例 msi 文件也有效。

多个实例的问题在于MajorUpgrade element does not work with multiple instances. If you inspect the resulting msi file with Orca you see only one entry with the UpgradeCode from the Product Element。来自您的实例的 UpgradeCodes 未在此 table 中侦听。要解决此问题,您必须手动将 UpgradeCodes 添加到此 table:

<Property Id="InstancesCount" Value="3"/>
<InstanceTransforms Property="INSTANCE_ID">
  <Instance Id="Instance_0" ProductCode="*" UpgradeCode="GUID_0"/>
  <Instance Id="Instance_1" ProductCode="*" UpgradeCode="GUID_1"/>
  <Instance Id="Instance_2" ProductCode="*" UpgradeCode="GUID_2"/>
</InstanceTransforms>
<Upgrade Id="GUID_0">
  <UpgradeVersion MigrateFeatures="yes" Minimum="0.0.0.0" Property="WIX_UPGRADE_DETECTED_0"/>
</Upgrade>
<Upgrade Id="GUID_1">
  <UpgradeVersion MigrateFeatures="yes" Minimum="0.0.0.0" Property="WIX_UPGRADE_DETECTED_1"/>
</Upgrade>
<Upgrade Id="GUID_2">
  <UpgradeVersion MigrateFeatures="yes" Minimum="0.0.0.0" Property="WIX_UPGRADE_DETECTED_2"/>
</Upgrade>

如果您删除了 MajorUpgrade element,那么您还必须添加:

<InstallExecuteSequence>
  <RemoveExistingProducts After="InstallValidate"/>
</InstallExecuteSequence>

这只能添加一次,将从 MajorUpgrade 自动添加。更新 table 中的默认 属性 名称是 WIX_UPGRADE_DETECTED。我们需要为每个实例使用一个单独的名称。我用“_”作为后缀。但也有其他可能。

如果我们使用 Orca 查看更新 table,我们现在可以看到我们所有的更新代码。但是有一个新的问题。如果我们安装第二个实例,则 MSIEXEC 在 FindRelatedProducts 操作中找到此 UpgradeCodes 之一的安装,并在 RemoveExistingProducts 中将其卸载。我们只能安装一个实例。所有以前的实例都被删除。

在 FindRelatedProducts 和 RemoveExistingProducts 操作之间,我们需要清除其他实例的 WIX_UPGRADE_DETECTED_xx 属性。只有当前实例的 UpdateCode 必须存在。我用一个小的 vbscript 动作来做到这一点:

<CustomAction Id="SetInstanceID" Script="vbscript">
InstancesCount = Session.Property( "InstancesCount" ) 
For i = 0 To InstancesCount - 1
    If CStr(i) &lt;&gt; instanceNumber Then
        Session.Property( "WIX_UPGRADE_DETECTED_" &amp; i ) = ""
    End If
Next
</CustomAction>

现在仅在 RemoveExistingProducts 中删除当前实例(如果已存在)。

实际上,MajorUpgrade 元素 确实 可用于多个实例。生成的实例转换将升级 table 的所有行替换为除 UpgradeCode 之外相同的新行,该行由该实例自己的 UpgradeCode 替换。如果您从 MSI 中提取实例转换(使用 SDK 中的 MsiDb.exe 工具提取子存储,其名称与 Instance/@Id 值相同,以便通过将它们应用到Orca 中的 MSI)。