ISWIX, LLC View Christopher Painter's profile on LinkedIn profile for Christopher Painter at Stack Overflow, Q&A for professional and enthusiast programmers

June 24, 2010

IsWix Release Cake

I am writing this entry with a deep sense of contrition. I was supposed to have published it 6 weeks ago while Chris Painter was off in paradise. Instead, my wife gave birth to our first child and the last six weeks have been a blur. So without further ado:


In order to celebrate the launch of IsWiX, I was given the solemn responsibility of picking up the launch party’s cake. In order to ensure maximal embarrassment, I tricked Chris and his dev team into taking the thumbs up picture. They were told that the picture was going to go on the SharePoint site.

Long time readers of the blog have seen Chris wade into the murky depths of the Red vs. Blue installer argument. In order to highlight the sea change in his view of WiX, I had the cake decorated in red icing. The coup de gras being the “thumbs up” picture added to the cake with the text “WiX Rules #1”.

Of course this was a gentle poke in the ribs, but it also speaks volumes as to how we all should avoid getting too locked into a specific tool. We should always focus on the right tool for the right job. Chris came to this conclusion and with his efforts our organization is currently embracing a decentralized installation model.

June 01, 2010

Improving InstallShield Product Configurations

InstallShield has a concept called "Product Configurations" that allows you to define similar yet different installers that generally contain different sets of features and metadata ( such as ProductCode, UpgradeCode, ProductName, ProductVersion ). It's a pretty powerful feature that uses flags to join products to features.

Consider the following:

Feature1
Flag 1

Feature2
Flag 2

Feature3
Flag 3

Product Configuration 1
Flag 1,3

Product Configuration 2
Flag 2,3

PC1 will get features 1 and 3 while PC 2 will get features 2 and 3.

Let's look at it another way:

Feature1
Flag A

Feature2
Flag B

Feature3
Flag A,B

Product Configuration 1
Flag A

Product Configuration 2
Flag B

Again, PC 1 will get features 1 and 3 while PC 2 will get features 2 and 3.

Make sense so far? Now here's where it falls apart IMO.

The flags are limited to 255 characters and when you scale to hundreds of features and dozens of products it's really easy to

a) run out of flag space
b) back yourself into a corner trying to figure out which products get which features based on which flags.
c) You are updating the installer source code every single time make a change for any of your products.

Basically it turns into a maintenance nightmare.

So here is I turn to a blend of WiX and InstallShield Automation to help solve the problem. Instead of declaring the product configurations in the Basic ISM project we split them out into WiX fragments that look like this:

WiX Config Files

<?xml version="1.0" encoding="utf-8"?>
<Include>
<?define ProductConfiguration="1"?>
<!-- define other meta here -->
<FeatureRef Id="Feature1"/>
<FeatureRef Id="Feature3"/>
</Include>

<?xml version="1.0" encoding="utf-8"?>
<Include>
<?define ProductConfiguration="2"?>
<!-- define other meta here -->
<FeatureRef Id="Feature2"/>
<FeatureRef Id="Feature3"/>
</Include>

You can then take this farther by the use of FeatureGroups's.

<?xml version="1.0" encoding="utf-8"?>
<Include>
<FeatureGroup Id="Client">
<FeatureRef Id="Feature1"/>
<FeatureRef Id="Feature3"/>
</FeatureGroup>
<FeatureGroup Id="Server">
<FeatureRef Id="Feature2"/>
<FeatureRef Id="Feature3"/>
</FeatureGroup>
</Include>

<?xml version="1.0" encoding="utf-8"?>
<Include>
<?define ProductConfiguration="1"?>
<!-- define other meta here -->
<FeatureGroupRef Id="Client"/>
</Include>

<?xml version="1.0" encoding="utf-8"?>
<Include>
<?define ProductConfiguration="2"?>
<!-- define other meta here -->
<FeatureGroupRef Id="Server"/>
</Include>

Build Automation

Since InstallShield doesn't 'do' WiX out of the box, the trick is to write a custom build automation step that parses the WiX XML documents and translates them into InstallShield source code using the COM Automation Interface. You can do this in any language that supports XML DOM parsing and COM. Personally I like like to use C# / .NET 3.5 with LINQ-To-XML for my DOM and a generated interop for the COM. Basically you have to parse the XML and walk the InstallShield project and wire it all up as if you had authored it all by hand.

I'll cover this part of it another day.