Blair Symes recently posted “Building 32-Bit and 64-Bit Installations from the Same InstallShield Project” on the Flexera’s InstallTalk blog. In it he describes how to build two MSI’s targetting opposite platform bitness using one InstallShield project. His example leverages a Type 51 custom action to assign INSTALLDIR at runtime based on the value of the ISReleaseFlags set during the build of each MSI.
Here’s a screen shot:
I wanted to take a moment to respectfully point out that this implementation is flawed, a better way to accomplish the task and finally an opportunity for InstallShield to improve their product with a new feature.
The problem comes from the condition and execution scheduling choices. First, let’s talk about the condition ISReleaseFlags (contains) X64. This condition should also be checking that INSTALLDIR doesn’t already have a value. Second the execution scheduling of Always Execute should really be Execute Only Once.
Why? Because failing to do some causes two defects in the resultant installer. First, attempting to pass INSTALLDIR at the command line will fail. The installer will continue to default the [ProgramFilesxx]MyCompanyNameMyAppName. Second, because the custom action is being called again in the InstallExecuteSequence the Browse capability in the CustomSetup dialog is effectively overridden. There are also other concerns such as trying to set a directory property in subsequent installer transactions such as repairs and upgrades/patches.
My entire architecture at my day job is built around Build Automation and ProductConfigurations. All of our installers bring together reusable components with unique branding which includes the value of INSTALLDIR. I’ve long known the complications of using custom actions so instead I use the ISWiProduct object’s INSTALLDIR property to build up the directory table before I build the project. This works really nicely ( including better looking Administrative Installation Extracts and Uncompressed Media ) and eliminates the need for the custom action. I find it ironic that InstallShield just posted six articles on how to use the automation interface in various obscure languages but missed this excellent opportunity to show how it can really be useful in a practical way.
Finally, there is a situation today where I’d have to use the Type 51 custom action: Multiple Instance Installers. InstallShield currently has the ability to define the ProductCode for each instance transform but it would be really cool if it also had the ability to define the INSTALLDIR at the ProductConfiguration level and the Instance level. The idea would be able to do something like:
ProductConfig A (default instance) INSTALLDIR [ProgramFiles]CompanyProductA
ProductConfig A (instance 1 ) INSTALLDIR [ProgramFiles]CompanyProductA-1
ProductConfig A (instance 2 ) INSTALLDIR [ProgramFiles]CompanyProductA-2
ProductConfig B (default instance) INSTALLDIR [ProgramFiles]CompanyProductB
ProductConfig B (instance 1 ) INSTALLDIR [ProgramFiles]CompanyProductB-1
ProductConfig B (instance 2 ) INSTALLDIR [ProgramFiles]CompanyProductB-2
Finally, for my WiX brothers, here is the equivilant code in WiX: