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

January 31, 2011

Comments on Setting INSTALLDIR During an Install

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]MyCompanyName\MyAppName.   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.

This goes to show how careful one must be with custom actions.  Even seemingly innocent Type 51 custom actions can cause undesired behavior.    If you don't understand this, I really suggest reading Stefan Krueger's immensely helpful  Installation Phases and In-Script Execution Options for Custom Actions in Windows Installer article.    ( The irony is this article was originally published by InstallShield back in 2001 so you'd think they already get it. )

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]Company\ProductA
ProductConfig A (instance 1 )   INSTALLDIR [ProgramFiles]Company\ProductA-1
ProductConfig A (instance 2 )   INSTALLDIR [ProgramFiles]Company\ProductA-2

ProductConfig B (default instance)   INSTALLDIR [ProgramFiles]Company\ProductB
ProductConfig B (instance 1 )   INSTALLDIR [ProgramFiles]Company\ProductB-1
ProductConfig B (instance 2 )   INSTALLDIR [ProgramFiles]Company\ProductB-2

Finally, for my WiX brothers, here is the equivilant code in WiX:






<SetProperty Id="INSTALLDIR"
             Value="[ProgramFiles64Folder]MyCompanyName\MyAppName"
             Sequence="both"  
             Before="AppSearch">
             ISReleaseFlags&gt;&lt;&quot;X64&quot;
</SetProperty>

WiX v3.5 Released

Rob has announced the release of Windows Installer XML 3.5.  I'd like to congratulate the WiX team for their achievement.

As I previously noted, I probably won't be able to explore this release at my day job due to our immutable requirement to support multiple versions of tools.  I've raised this issues many times over the past couple of years and it looks like Rob has now taken notice of the problem:

Also, it is important to note that Votive in WiX v3.5 does not install side by side with WiX v3.0. This is an unfortunate design issue that we hope is fixed for WiX v3.5 upgrades to WiX v3.6.


I'm really looking forward to v3.6 ( because of Burn ) and  hope to see this improvement in v3.6 so that I can actually use it in my environment.   Until then, I will be using v3.5 in my own personal environment and I suggest that anyone who can move forward do so. 

January 22, 2011

Upgrade vs No Upgrade and Windows Installer XML

A lot is side in the MSI SDK about servicing strategies.  Much of it is confusing and has to do with the intricate details of  Major vs Minor vs Small Upgrades and Upgrades shipped as MSI's or as Patches.  The UpgradeCode property itself is defined as a "GUID representing a related set of products".

If you do this all correctly you get a nice user experience.   For example I might install one version of a text editor and then later upgrade to the latest version of the text editor.   

But what really isn't mentioned in the SDK is  what to do when you have a related product but you don't want to do an upgrade.   Perhaps what you really want is a side by side installation of a new version of a product.

For example,  how you feel if you installed Visual Studio 2008 and then when you installed Visual Studio 2010 it remove Visual Studio 2008?   What if you insalled InstallShield 12 and when you installed InstallShield 2011 it removed InstallShield 12?

Would you really be ok with that?   I wouldn't.  I couldn't possibly move all of my software baselines to a newer tool or have 2 machines on my desktop for the two different sets of tools.

These are times when you must design both your application and your installer to be able to support side by side installations of different versions of the software. 

Sadly, the WiX team has made this choice for me.  Rather then support  Votive 3.0 and Votive 3.5 side by side installations with Visual Studio 2008 and Votive 3.5 with Visual Studio 2010 they have chosen to do a Major Upgrade and support only Votive 3.5 on Visual Studio 2008 and Visual Studio 2010.

To make it even more interesting they have broken backwards compatibly by changing the name of the MSBuild Targets file that the .wixproj points to.

Basically the software was designed that if you want to use Votive 3.5, you gotta be all in.

Well, perhaps some people will be ok with that.  If you are new to WiX without a huge previous investment or you don't use Votive perhaps you will be ok also.  However, for the massive environment that keeps me busy at my day job I say:

Pass

I make this call because WiX 3.5 only brings marginal benefit to my situation while requiring me to make a substantial commitment with a lot of associated risk. 

It's obviously too late to fix this for 3.5 as this would be the sort of high risk last minute activity that any setup developer hates.  However I hope to see a different story for 3.6.  I'd like to be able to have the latest 3.5 installed on my personal machine at home while also installing the latest 3.6 weekly release.  When 3.6 goes RTM one day I hope to have 3.5 and 3.6 installed side by side.

As an aside, Industrial Strength Windows Installer XML will work with any combination of Visual Studio 2008, 2010 or None and Windows Installer XML 3.0, 3.5, 3.6 or none.   IsWiX technically just authors XML files so it has no physical dependencies on either VS or WiX other then a shared understanding of the wix.xsd file.

January 19, 2011

Augmenting InstallShield using Windows Installer XML - Windows Services

In my last blog I explained how you could use a WiX module to extend InstallShield to accomplish installing certificates.  I also mentioned that you could use WiX to inject  Windows Services into InstallShield 2010 Limited Edition even though the tool wasn't designed to support this.

Below is an example of what said WiX source code would look like.   I post this not as some attempt to 'hack' InstallShield LE but more a spirit of  I really don't want to see former VDPROJ developers continuing the horrible practice of writing InstallUtil custom actions to install services.

As an aside, 14 of the 16 lines of XML were authored by IsWiX.  I only had to add the ServiceInstall and ServiceControl elements.  One of these days I'll get around to finishing the Services Designer so IsWiX can do all the authoring.


<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
  <?define SourceDir="."?>
  <Module Id="WindowsService" Language="1033" Version="1.0.0.0">
    <Package Id="f4e004d1-4fc1-4dab-855d-c46fc2ec3702" Manufacturer="WindowsService" InstallerVersion="200" />
    <Directory Id="TARGETDIR" Name="SourceDir">
      <Directory Id="MergeRedirectFolder">
        <Component Id="owcB7461B87B05DCA45F57E1CB0917F32A7" Guid="380bbddd-daa7-0744-517b-37da768f5570">
          <File Id="owfB7461B87B05DCA45F57E1CB0917F32A7" Source="$(var.SourceDir)\WindowsService.exe" KeyPath="yes" />
          <ServiceInstall Id="installWS" Name="WindowsService" DisplayName="Windows Service" Description="Windows Service" Start="auto" Type ="ownProcess" ErrorControl ="normal"/>
          <ServiceControl Id="controlWS" Name="WindowsService" Remove="both" Stop ="both" Start="install" Wait ="no"/>
        </Component>
      </Directory>
    </Directory>
  </Module>
</Wix>

Augmenting InstallShield using Windows Installer XML - Certificates

I've blogged in the past how I like to blend WiX with InstallShield and today I'd like to post another example of the usefulness of these two tools together.

Recently I was creating an installer that need to install a trusted root certificate.  I looked at InstallShield 2010 and the only certificate support I could find was for creating IIS websites and assigning server certificates.  ( As an aside, I never quite understood the usefulness of that outside of a controlled corporate environment where you are setting up many servers to belong to the same farm or to an application where you will register a hostname in DNS and all customers know the server by the same name.  Also let's not mention distributing private keys in MSI's along with the passphrases needed to deploy them.  Really?? )

So I looked at WiX's documentation and found the Certificate Element in the IIS Extension.    Sure enough it has much broader support and can easily get the job.   So I decide to create a WiX Merge Module with a snippet of code similar to:



<?xml version="1.0" encoding="UTF-8"?>
<?define SourceDir="."?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:iis="http://schemas.microsoft.com/wix/IIsExtension">
  <Module Id="InstallCertificate" Language="1033" Version="1.0.0.0">
    <Package Id="00000000-0000-0000-0000-000000000000" Manufacturer="YourCompanyHere" InstallerVersion="200" />
    <Binary Id="cert" SourceFile="$(var.SourceDir)\mycert.pfx"/>
    <Directory Id="TARGETDIR" Name="SourceDir">
      <Directory Id="MergeRedirectFolder">
        <Component Id="certs" Guid="00000000-0000-0000-0000-000000000000">
          <CreateFolder/>
          <iis:Certificate Id="cert" BinaryKey="cert" Name="cert" Overwrite="yes" SoureLocation="localMachine" StoreName="root"/>
        </Component>
      </Directory>
    </Directory>
  </Module>
</Wix>

I now end up with a nice encapsulation ( InstallCertificate.msm ) that I can add to my InstallShield project via the Redistributables tab. Build the MSI and test on a VM proves that it works.


This pattern can also be used with InstallShield 2010 Limited Edition and with a little bit of creative thinking you can quickly get IS2010LE to do all kinds of things that it was crippled to not be able to do. The best part is you are following very good practices while doing it and not trying to hack a solution together like you would be with Visual Studio Deployment Projects and InstallUtil Custom Actions.

January 11, 2011

DC Universe Online Uninstaller Issues

I was searching twitter for InstallShield when a couple of links led me to this great thread:

DC Universe Online Uninstaller Issues ( Google Cache of Sony Online Entertainment )

It seems customer service was announcing some bugs in their uninstall.  Now I'm not sure what will actually happen if the user clicks "Yes" but I do know I don't ever, ever want to see this dialog in my uninstall:


But the real kicker came when Customer Service  "TSR-AndyD" posted:

I'm sure you all realize that the focus of the development staff is currently going to be bmaking [sic] the game as awesome as possible for the retail release. The broken uninstaller is a forgivable and understandable over-sight.

Whiskey - Tango - Foxtrot????

It's now 2010 and with all this talk of Agile and CI, developers still don't have a clue why it's so important to make a proper install ( and uninstall ). 

Course this is Sony we are talking about.  Less we forget about their rootkit incident.
The bright side is some bright folks discussing the issue over this thread actually seem to get it.

January 05, 2011

Resuming Course

A few months ago I mentioned that I was going to take a break from installers and do .NET development. It was a very enlightening experience as I was able to gain a new perspective while improving my skills and helping a project that was in crunch mode. Alas things have slowed down a bit and I'm resuming my duties on the Install Services team.

One thing I did realize about myself is that I'm a High Functioning Windows Installer Addict. It's just so in my blood that it's sometimes hard to think about any thing else. Sorry, I'm just a freak of nature or something. So I'm back... ready to get my fix.