如何创建 MSI UI,允许在维护模式下运行时卸载特定实例
我们正在使用 WIX 3.6 为 Silverlight/WCF 应用程序创建一个安装程序。 我们需要能够安装多个实例来提供例如“实时”、“测试”和“演示”。 每个实例必须能够运行不同的版本并独立升级。 这允许在升级“Live”之前在“Test”中安装新版本。
我正在使用 InstanceTransforms 机制来切换 ProductCode 和 CustomActions 来切换最多 10 个实例的 UpgradeCode。
我还设法通过自定义 MaintenanceTypeDlg 创建一个 UI,以允许在不使用命令行的情况下安装新实例。我设置了 MSINEWINSTANCE=1 和 TRANSFORMS=:Instance,其中 Instance 是第一个在执行安装之前在注册表中找不到的实例。
我还可以通过主要升级路径升级默认实例。 添加/删除程序上的删除和修复选项也可以正常工作。
我遇到问题的地方是创建一种用于升级、修复或从维护对话框中删除特定实例的机制。
我创建了一个 ComboBox,它使用 CustomAction 填充所有已安装实例的 id 和名称,但我无法找到一种方法将该信息从 InstallUISequence 可靠地传递到 InstallExecuteSequence。
我尝试指定 TRANSFORMS=:Instance 但服务器 MSI 删除了该属性。 我尝试指定 MSIINSTANCEGUID={[SelectedGuid]},但服务器 MSI 抱怨该属性的使用无效,因为它不是多实例安装。
我设法使用 TRANSFORMS=:InstancetoUpgrade 命令行来升级安装特定实例,并将 UpgradeTable 设置的属性覆盖为正确的实例 ProductCode,但是它会缓存 TRANSFORMS,并且如果没有 TRANSFORMS= 则始终应用该转换在命令行上指定。 TransformsSecure 策略已设置,但我们无法在客户站点上更改此策略。
我无法找到 MSI 或 WIX 的任何文档或示例来显示在 InstallUISequence 和 InstallExecuteSequence 之间设置的正确属性,以强制服务器升级、修复或删除 MSI 中默认实例以外的实例。用户界面已启动。
如果有人设法使多实例 MSI 的此或多实例 MSI 的类似方面正常工作,请发布 CustomActions、属性等的任何示例,或有关如何使其正常工作的提示。
编辑:
我已设法通过设置属性获得新版本的 MSI 来升级特定实例: UPGRADEFOUND={PreviousInstanceGUID} TRANSFORMS=:实例;
但是,如果我尝试再次运行 MSI 来升级差异实例,TRANSFORMS 已设置为我刚刚升级的实例。 我的 UI 无法区分双击的 MSI 或从脚本运行的 MSI 来升级/修复特定实例。 在维护模式下运行时,切换到服务器时 MSI 似乎也会忽略 TRANSFORMS 属性的任何更改。 我需要一种方法来处理这样一个事实:在某些情况下它将处于维护模式,而其他情况则处于升级模式。 实际上,当在 UI 中选择差异实例时,我需要能够重新运行 FindRelatedProducts 和 AppSearch。
We are creating an installer using WIX 3.6 for a Silverlight/WCF application.
We require the ability to install multiple instances to give e.g. "Live", "Test" and "Demo".
Each instance must be able to run a different version and be upgraded independently.
This allows a new version to be installed in "Test" before upgrading "Live".
I am using the InstanceTransforms mechanism to switch the ProductCode and CustomActions to switch the UpgradeCode for up to 10 instances.
I have also managed to create a UI by customising the MaintenanceTypeDlg to allow installing new instance without using the command line. I set MSINEWINSTANCE=1 and TRANSFORMS=:Instance where Instance is the first of my instances that can't be found in the registry before ExecuteInstall.
I can also upgrade the default instance through the major upgrade path.
Remove and Repair options on Add/Remove programs also work correctly.
Where I am having problems is in creating a mechanism for Upgrading, Repairing or Removing a specific instance from the Maintenance dialog.
I have created a ComboBox which is populated using a CustomAction with the id and names of all installed instances, but I cannot find a way of reliably passing this information from the InstallUISequence to the InstallExecuteSequence.
I have tried specifying TRANSFORMS=:Instance but the Server MSI deletes the property.
I have tried specifying MSIINSTANCEGUID={[SelectedGuid]}, but the server MSI complains that it is an invalid use of the property because it is not a multiple instance install.
I managed to get an upgrade install of a specific instance working using the command line with TRANSFORMS=:InstancetoUpgrade and overwriting the property set by the UpgradeTable to the correct instance ProductCode, however it caches the TRANSFORMS, and always applies that transform if no TRANSFORMS= is specified on the command line.
The TransformsSecure policy is set, but we will not be able to change this policy on customer sites.
I have not been able to find any documentation or examples for MSI or WIX that show the correct properties to set between the InstallUISequence and the InstallExecuteSequence to force the server to Upgrade, Repair or Remove an instance other than the default one in the MSI from which the UI was launched.
If anyone managed to get this or a similar aspect of multi-instance MSIs working, please post any samples of CustomActions, Properties etc, or hints on how to get this working.
EDIT:
I have managed to get a new version MSI to upgrade a specific instance by setting properties:
UPGRADEFOUND={PreviousInstanceGUID} TRANSFORMS=:Instance;
However if I try and run the MSI again to upgrade a difference instance TRANSFORMS is already set to the one I just upgraded.
My UI cannot distinguish between the MSI being double-clicked or being run from a script to upgrade/repair a specific instance.
It also looks like the MSI ignores any changes to the TRANSFORMS property on switching to the server when running in Maintenance mode.
I need a way of handling the fact that for some instances it will be in maintenance mode and others upgrade mode.
In effect I need to be able to re-run FindRelatedProducts and AppSearch when a difference instance is chosen in the UI.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我在 http://www.codeproject.com/ 找到的文章Articles/37825/WIX-SSRS-Custom-Assembly-Installer 是实现此功能的最大帮助。
看起来我缺少的步骤是在升级和安装上设置 MSINEWINSTANCE=1 。
代码项目示例使用自定义操作来确定已安装的实例,并使用结果填充自定义 MSI 表,以及使用实例填充列表框。这样做的另一个好处是不需要大量带有 RegSearch 元素的公共属性来查找已安装的实例。
当按下“选择实例”对话框的“下一步”按钮时,将调用第二个自定义操作。这会将 TRANSFORMS、Installed、MSINEWINSTANCE、NEWPRODUCTFOUND、UPGRADEFOUND 和 MIGRATE 设置为适当的值。它重复了 FindInstalledProducts 的一些功能。键值包括:
新实例:
相同版本(维护):
已安装较新版本:(应给出降级错误)
已安装较旧版本:(升级)
代码项目示例在准备序列中将选择实例对话框显示为弹出窗口因此它在 FindRelatedProducts 和 AppSearch 之前运行。也可以通过按 MaintenanceTypeDlg 中的“返回”来显示它。然而,当尝试将其插入其他对话框序列时,这会出现问题,因此我将其设为普通序列对话框,并且它仍然有效。
为了正常工作,需要为所有实例设置 TRANSFORMS,因此永远不会安装默认实例。需要为此创建一个与任何其他 ProductCode 不同的虚拟 ProductCode。我使用了 Wix“*”约定。我的默认 UpgradeCode 与第一个转换的升级代码相同,但这可能应该不同,甚至可以省略它。
我还发现我需要使用 CustomAction 和特定实例的 UpradeCode 来填充 UpgradeTable,以避免它尝试删除升级中的所有其他实例。
The article I found at http://www.codeproject.com/Articles/37825/WIX-SSRS-Custom-Assembly-Installer was the biggest help in getting this working.
It looks like the step I was missing was setting MSINEWINSTANCE=1 on Upgrades as well as installs.
The code project example uses custom actions to determine what instances are already installed and populates a custom MSI table with the results, as well as populating a ListBox with the instances. This has the added benefit of not requiring lots of public properties with RegSearch elements to find the installed instances.
A second custom action is called when the Next button of the Select Instance dialog is pressed. This sets TRANSFORMS, Installed, MSINEWINSTANCE, NEWPRODUCTFOUND, UPGRADEFOUND and MIGRATE to appropriate values. It duplicates some of the functionality of FindInstalledProducts. The key values are:
New Instance:
Same Version (Maintenance):
Newer version already installed: (Should give a downgrade error)
Older version installed: (Upgrade)
The code project example showed the Select Instance Dialog as a popup, in the Prepare sequence so it is run before FindRelatedProducts and AppSearch. It can also be shown by pressing Back from the MaintenanceTypeDlg. This however has problems when trying to insert it into a sequence of other dialogs, so I made it an ordinary sequence dialog and it still works.
In order to work correctly the TRANSFORMS needs to be set for all instances, so the default instance is never installed. A dummy ProductCode needs creating for this different from any other ProductCode. I used the Wix "*" convention. I have the default UpgradeCode is the same as the first transformed upgrade code, but this should probably be different, and it may even work to omit it.
I also found that I needed to populate the UpgradeTable using a CustomAction with the UpradeCode of the specific instance to avoid it trying to remove all the other instances on an Upgrade.
除非您禁止 ARP,否则每个实例都应在“添加/删除程序”中获得其自己的条目,并且当您单击“更改”时,将处于该实例 ProductCode 所特有的维护模式。
我错过了什么吗?也许您正在抑制 (ARPSYSTEMCOMPONENT) 并且您想要编写一个为所有实例提供服务的 UI。如果是这样,那是可以做到的,但它会比几个问题要大得多。
Unless you are supressing ARP, each instance should get it's own entry in Add/Remove Programs and when you click change be in a maintenance mode that's unique to that instances ProductCode.
Am I missing something? Perhaps you are suppressing (ARPSYSTEMCOMPONENT) and you want to write a single UI that services all of the instances. IF so, that can be done but it'd be way bigger then a handful of questions.