我正在使用实例转换在同一台计算机上多次安装相同的产品。 启动.msi安装文件时,我在命令行上传递TRANSFORMS =“:X”(以及安装所需的其他几个变量),其中X是要使用的程序的版本。
在Product.wxs文件中,我使用InstanceTransforms标记分配一个新的ProductCode,例如:
<Property Id="INSTANCEID" Value="Default"/>
<InstanceTransforms Property="INSTANCEID">
<Instance Id="I1" ProductCode="$(guid.NewGuid())"/>
<Instance Id="I2" ProductCode="$(guid.NewGuid())"/>
<Instance Id="I4" ProductCode="$(guid.NewGuid())"/>
<Instance Id="I3" ProductCode="$(guid.NewGuid())"/>
<Instance Id="I5" ProductCode="$(guid.NewGuid())"/>
<Instance Id="I6" ProductCode="$(guid.NewGuid())"/>
<Instance Id="I7" ProductCode="$(guid.NewGuid())"/>
<Instance Id="I8" ProductCode="$(guid.NewGuid())"/>
<Instance Id="I9" ProductCode="$(guid.NewGuid())"/>
</InstanceTransforms>
此外,UpgradeCode在自定义操作中添加到UpgradeTable,相关代码为:
Database db = session.Database;
session.Log("Get DB: {0}", db.FilePath ?? string.Empty);
string sqlInsertSring = db.Tables["Upgrade"].SqlInsertString + " TEMPORARY";
session.Log("DB Tables, querying with SQL: {0}", sqlInsertSring);
View view = db.OpenView(sqlInsertSring);
session.Log("OpenView, adding two new records to the UpgradeView.");
session.Log("Inserting line: {0}, null, {1}, null, 512, null, \"UPDATE\"",
session["UpgradeCode"], session["ProductVersion"]);
view.Execute(new Record(new object[] { session["UpgradeCode"], null,
session["ProductVersion"], null, 512, null, "UPDATE"}));
session.Log("Inserting line: {0}, {1}, null, null, null, 0, \"NEWERVERSIONINSTALLED\"",
session["UpgradeCode"], session["ProductVersion"]);
view.Execute(new Record(new object[] { session["UpgradeCode"],
session["ProductVersion"], null, null, 0, null, "NEWERVERSIONINSTALLED" }));
view.Close();
好的,到目前为止一切顺利,这适用于安装,允许我成功安装同一程序的两个实例。但是,更新似乎不起作用。我可以升级其中一个实例,但是在升级第二个实例时,转换无法正常工作,另一个实例会再次升级。
示例:两个实例(I1和I2)。升级I2工作正常。但是,当我随后尝试更新I1时,它只是再次更新I2(尽管传递了正确的转换)。
MSI的日志显示转换首先恢复为I1(应该如此),然后再次设置为I2(原因我无法理解):
- MSI (s) (B0:F8) [09:06:48:745]: Running product '{C33371A0-C32A-4120-BD8F-ACDC79E13458}' with elevated privileges: Product is assigned.
- MSI (s) (B0:F8) [09:06:48:776]: PROPERTY CHANGE: Modifying TRANSFORMS property. Its current value is ':I2'. Its new value: ':I1'.
- MSI (s) (B0:F8) [09:06:48:823]: PROPERTY CHANGE: Adding DATADIR property. Its value is
MSI (s) (B0:F8) [09:06:49:463]: PROPERTY CHANGE: Adding CURRENTDIRECTORY property. Its value is 'C:\Users\Administrator\Desktop'.
- [Further arguments passed]
- MSI (s) (B0:F8) [09:06:49:494]: PROPERTY CHANGE: Adding CLIENTUILEVEL property. Its value is '2'.
- MSI (s) (B0:F8) [09:06:49:572]: PROPERTY CHANGE: Adding CLIENTPROCESSID property. Its value is '6424'.
- MSI (s) (B0:F8) [09:06:49:587]: Machine policy value 'DisableAutomaticApplicationShutdown' is 0
- MSI (s) (B0:F8) [09:06:49:634]: RESTART MANAGER: Disabled by MSIRESTARTMANAGERCONTROL property; Windows Installer will use the built-in FilesInUse functionality.
- MSI (s) (B0:F8) [09:06:49:681]: PROPERTY CHANGE: Adding MsiSystemRebootPending property. Its value is '1'.
- MSI (s) (B0:F8) [09:06:49:728]: PROPERTY CHANGE: Modifying TRANSFORMS property. Its current value is ':I1'. Its new value: ':I2'.
- MSI (s) (B0:F8) [09:06:49:821]: TRANSFORMS property is now: :I2
最后一行很重要:TRANSFORMS属性再次设置为I2,这意味着安装将更新实例I2而不是实例I1。
为什么会发生这种情况? TRANSFORMS正确传递,我无法理解为什么该属性会再次被撤回。
(如果需要更多代码或表达,我很乐意提供)。
编辑:BTW我正在使用WiX工具集3.7。编辑2:对于安装,我使用以下参数调用.msi:
MSINEWINSTANCE=1 TRANSFORMS=":I[N]" [Further parameters] (where N is the Instance)
对于更新,我在没有MSINEWINSTANCE的情况下调用.msi,直接从TRANSFORMS部分开始
作为一个脏修复,我现在正在卸载/安装更新,这不完全是我的计划。
答案 0 :(得分:3)
你没有提到MSINEWINSTANCE property所以也许你没有正确地调用安装。此属性应设置为1。有关详细信息,请参阅:Installing Multiple Instances with Instance Transforms。
我也在我的博客上解释了这个过程:(哇,真的是8年前吗?)
Multiple Instance MSI's and InstallShield 12
更新
我能够使用WiX和IsWiX正确实现这一点。
步骤1:使用IsWiX多项目解决方案加速器模板创建MSI / MSM项目。
步骤2:将文件添加到合并模块,以便安装程序具有一个包含文件作为要安装的密钥路径的组件。 (这是必需的,因为a)您需要注册至少一个组件才能考虑安装功能/产品; b)具有非文件的密钥路径的组件必须使用不同的guid进行变更,并根据实例ID进行条件安装。要解决这个问题并将其设为简单,只需创建一个以文件作为键路径的组件
步骤3:将以下XML添加到主要wxs文件Product.wxs:
<SetProperty Id="INSTALLLOCATION" Value="[ProgramFilesFolder][Manufacturer]\[ProductName]" Before="AppSearch" Sequence="first">Not INSTALLLOCATION and Not Installed</SetProperty>
<Property Id="InstanceId" Value="0"/>
<InstanceTransforms Property="InstanceId">
<Instance Id="I1" ProductCode="*" UpgradeCode="{10E90C30-F117-4EE8-A084-25E4D0076CE4}" ProductName="ProductName-1" />
<Instance Id="I2" ProductCode="*" UpgradeCode="{919F5399-4E7A-4D8A-9484-A85D0F5E2C77}" ProductName="ProductName-2" />
<Instance Id="I3" ProductCode="*" UpgradeCode="{0BEAEF92-1821-4909-A83A-9B2AE2194AAC}" ProductName="ProductName-3" />
</InstanceTransforms>
如果未在命令行传递值并且以前未安装产品(在这种情况下目录是不可变的),则此代码会在首次安装时改变安装目录。我还使用*来获取随机ProductCode和传递UpgradeCode值,因为项目模板使用了MajorUpgrades开箱即用,每个实例都是一个独特的产品系列,用于升级。最后,我将ProductName转换为添加/删除程序中的唯一,并驱动安装位置转换。
安装主要实例:
msiexec /I ProductName.msi
安装辅助实例:
msiexec /I ProductName.msi MSINEWINSTANCE=1 TRANSFORMS=":I1"
msiexec /I ProductName.msi MSINEWINSTANCE=1 TRANSFORMS=":I2"
msiexec /I ProductName.msi MSINEWINSTANCE=1 TRANSFORMS=":I3"
请注意在TRANSFORMS属性中使用“:”。这指定了Storages表中的嵌入式转换。
两个安装在“程序文件和程序和功能”中并排显示。