Friday, June 11, 2010

Transforms and upgrades

Upgrading shall not be easy. In our installer we are using an MST file to configure the server connection for our clients so that they shouldn't need setting this up manually.

The transform file path is entered in the Setup.exe MSI Command Line Arguments in Installshield. Everything ok so far.

But when upgrading to a newer version where the server configuration has changed, we'd love the installer to detect changes in the MST file and upgrade the client's configuration when upgrading. The problem now is that the installer uses a cached version of the MST file, and therefore the new configuration wont be applied!

I'll get back when or if I find a solution to this problem.

Monday, June 07, 2010

Upgrades, uninstall and major versions

While I was trying to make the new client installer uninstall previous versions of our software, I ran into a few issues that took a while to solve.

First and foremost, the previous installer (custom-built) didn't contain an upgrade code (which uniqely identifies a product across versions) that I could use in my new MSI installer's upgrade table to make sure it was uninstalled. This was simple, just create a custom action that reads the uninstall information from the registry and runs the uninstall string if it exists for your product.

Next I tried to tell Windows installer to remove two additional products that were installed using MSI installers. I used the upgrade table with the upgrade codes from the two products I wanted to uninstall.

When running the installer, only one of the products were removed, and the log told me that the other one was skipped because it was installed in a different context (machine, not for this user only).

When I removed the product that successfully was uninstalled and reran the installation, the product that was previously skipped was uninstalled! This baffled me, and I tried a lot of different solutions until I finally had to revert to a rather dirty solution.

First of all, this is whats happening when you are uninstalling previous products:
  1. When the installer runs the FindRelatedProducts action, it looks in the Upgrade table to find what products it should search for. If it finds a product installed (using the UpgradeCode in the Upgrade table), it sets the value of the property (actionprop column) for the product in the Upgrade table to the Product code (installed version of product)
  2. The uninstallation happens in the RemoveExistingProducts action which uninstalls those products marked for uninstallation (from the FindRelatedProducts action)
The problem in my case was that the FindRelatedProducts action skipped one of the products, so I had to include a small vbscript that was run before the RemoveExistingProducts action that found the product code for the product I wanted to remove and updated the according property so that it would be uninstalled:

set oWI = CreateObject("WindowsInstaller.Installer")
set related = oWI.RelatedProducts("YOUR_UPGRADECODE_HERE")
if related.Count = 1 then
Property("ACTIONPROPERTY_NAME_HERE") = related.Item(0)
end if

Forcing the product code to be set solved the issue I had even though I never found out what was wrong with the FindRelatedProducts action not picking up both products.

Tuesday, February 23, 2010

Extract COM information during build time causes Installshiled to hang

InstallShield uses a tool to extract COM information (spying on the registry) called IsRegSpy.exe. It is trying to register COM libraries and watching what happens in the registry to capture all the keys and values written during registration.

After adding some our own internal libraries I noticed that the IDE startet to hang when extracting COM information from the components in the setup project. After inspecting what was happening using ProcExplorer from Microsoft ( I saw that the IDE spawned IsRegSpy.exe but IsRegSpy.exe never seemed to return.

After digging back and forth for a while, I tried to extract the COM information from within the InstallShield IDE to avoid getting this error each time we built the project. The same thing happened, the IDE launched IsRegSpy.exe and stopped responding.

I tried killing IsRegSpy.exe from within ProcExplorer, and noticed that InstallShield managed to add the correct COM information to the IDE! It also turned off the "Extract COM at build" setting for the component! Doing this for all COM components in the Setup project I managed to get past the problem of hanging the IDE when building.

EDIT: The last paragraph was obviously written in a very optimistic tone.. Some of the information was saved, some was not. My final solution was to export the registry hives before and after registering the dlls and then diffing the output...

Wednesday, February 17, 2010


Seems to be rather easy using InstallShield. There are several different options to choose from. You can add all the languages you want to support to your installation, or you can build seperate installations for each language.

NOTE: The language of the installer itself and the language your application is set up to run in are not the same.

I chose to build sepearate deployment packages for each language our application is using. The reasoning behind this is that each language component weights in at around 10 megs which could be a problem to distribute to remote users when updating or servicing the application.

Using different releases and configurations under the Media/Releases node gives me the opportuntity to build more than one setup.exe from my project. I have also integrated the build of each setup into our build system using some custom code for spawning Install Shield.

To get automatic resolving of which features that should go into which of my language dependant distributions, I have set the languages property for these features to a specific language (not Language Independent). When setting a release configuration 's data languages, ui languages and default language to a given language, only those features with either the same language as the configuration (or language independent) will be included in the setup!

Transforms and Setup.exe

When starting out with the deployment project, I tried to define some areas where I had to do some research to be certain that we had a solution that was scalable and easy to maintain.

One of the first issues I ran into was the need for using transforms to change some property values in the MSI package. The background for this requirement is that our app is a typical client/server-based application where our clients perform a server installation where they customize the installation against their database setup and file locations etc.

The cusomization performed in the server setup must be replicated into the client setup so that end users shouldn't have to select odbc connections or file locations upon installation.

The first issue here is how we can make the Server Setup process modify the client installer so that it depolys the client package with the predefined settings. To make this work, we've decided to use transform files.

A transform file is a simple msi database that contains tables just like another msi file. It is used to override values in the msi file it is transforming.

Creating a transform (.mft) file is simple using InstallShield. Just select new project and choose the Transform project template. InstallShield will ask you to provide the msi-file for which you are creating a transform, so you have to have it built already.

After creating the transform file, add it to your installation project under the support file section. You can now tell setup.exe to run it by providing command lines to the msi file in the setup.exe package. Select your setup release in InstallShield (this post is about transforms, so if you only have an msi project, please stop reading..) and switch to the Setup.exe tab. In the MSI Command Line Arguments property, enter TRANSFORMS=name of your mst file.

When we're ready to start generating our own transformation files that lives outside setup.exe, we can remove the transformation file from our setup project and provide it alongside the setup itself.

Welcome back...

I'm currently working on a new MSI-based installer for our main product, and since I tend to forget how I solve the different parts of building an installation from the last time I built one, I've decided to document some of the more important solutions I find here.