Question

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.

Was it helpful?

Solution

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:

session["TRANSFORMS"] = string.Format(":{0}", nextAvailableInstance);
session["Installed"] = "";                                  
session["MSINEWINSTANCE"] = "1";
session["NEWERPRODUCTFOUND"] = "";
session["UPGRADEFOUND"] = instance.ProductCode;
session["MIGRATE"] = instance.ProductCode;

Same Version (Maintenance):

session["TRANSFORMS"] = string.Format(":{0}", selectedInstance);
session["Installed"] = "1";
session["NEWERPRODUCTFOUND"] = "";
session["UPGRADEFOUND"] = "";
session["MIGRATE"] = "";

Newer version already installed: (Should give a downgrade error)

session["TRANSFORMS"] = string.Format(":{0}", selectedInstance);
session["Installed"] = "1";
session["NEWERPRODUCTFOUND"] = instance.ProductCode;
session["UPGRADEFOUND"] = "";
session["MIGRATE"] = "";

Older version installed: (Upgrade)

session["Installed"] = "";
session["MSINEWINSTANCE"] = "1";
session["NEWERPRODUCTFOUND"] = "";
session["UPGRADEFOUND"] = instance.ProductCode;
session["MIGRATE"] = instance.ProductCode;

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.

OTHER TIPS

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top