Understanding Generic Transforms

By Leslie Easter

There are things that once explained, seem obvious. Generic transforms are one of those. A generic transform is one that can be applied to any .MSI without modification—a very powerful method of implementing standard changes across all deployed packages. You may find yourself repetitively making the same changes to existing vendor packages. If that sounds familiar, then a generic transform could be just what you need. In this blog post, we’re going to walk through the creation of a generic transform. Along the way we’ll also walk through some best practices.

The first thing we’ll need to do is create the transform. We’ll do this by creating a new transform project within InstallShield. Use FileàNew, and select the Transform project icon. We’ll call our transform, ‘Generic’. Provide a location to create the transform and select OK to launch the Open Transform Wizard.

Within the wizard, you’ll be prompted for the path and name of the target .MSI file. The target .MSI should be a rather simple package. Because we’re creating a generic transform, the package shouldn’t matter too much. However, any change you want to make shouldn’t already exist in the target package. Also, even though the wizard prompts for additional transforms, you shouldn’t include any other transforms at this point. The wizard concludes by providing the opportunity to include a response transform. You should decline this option as well.

After the transform project opens within InstallShield, we’ll move to the Installation Designer tab to start making our changes. Normally there are two different areas that generic transforms include: adding or modifying public properties and adding registry keys. Other items can be added as well, but we’ll focus on these specific changes.

On the left-hand side, select Behavior and LogicàProperty Manager from the view list. Within this view we can add or modify properties. Depending on your company’s software deployment best practices you may already have a list of properties that are consistently applied to all packages. Here are some common settings:

ARPNOMODIFY                           1
REBOOT                                    ReallySuppress
ALLUSERS                                 1
TRANSFORMSSECURE              1

You could also take this time to include a generic transform property that contains a version number for this transform. Doing this allows you to differentiate changes to your generic transform over time.

As a word of caution—if a property that you want to add already exists in the Property Manager but with a different value, you cannot simply change the value. You’ll need to delete the entire row and add the property as a new entry.

Let’s move on to adding registry keys. We’ll need to move over to OrganizationàSetup Design for this change. It’s critical that adding anything (registry keys, files, etc.) must be done to a new feature instead of adding to an existing one. After all, generic means that we cannot depend on anything pre-existing in the target package. We’ll start by creating a new feature. The name of this feature should be unique—something like ‘CompanyName_Audit’ should do nicely. To this feature, we’ll add our components. These should also be unique. I would recommend adding your company name to the component names as well. In this case, we’ll create two components: one for data that is installed and removed with the application and a second for registry data that is permanent. Let’s call the first one CompanyName_AuditHistory and the second we’ll call CompanyName_AuditInstalled. To make this work, be sure to set the Permanent property to Yes for our AuditHistory component.

Once the component names have been created, we’ll import or create the registry keys to each component. A typical collection of registry keys for the AuditHistory component would look something like the following:

 [HKEY_LOCAL_MACHINESoftwareYourCompanyNameHistory[ProductName] – v[ProductVersion] – [Date] – [Time]]

"ProductName"="[ProductName]"

"ProductVersion"="[ProductVersion]"

"BlocksRemaining"="[PrimaryVolumeSpaceRemaining]"

"InstalledBy"="[LogonUser]"

"InstalledFrom"="[OriginalDatabase]"

"InstalledOn"="[Date] – [Time]"

"ProductVersion"="[ProductVersion]"

"Workstation"="[ComputerName]"

"ProductCode"="[ProductCode]"

"Transforms"="[TRANSFORMS]"

For the AuditInstalled component, we would add a collection of registry keys such as:

 [HKEY_LOCAL_MACHINESoftwareYourCompanyNameInstalled[ProductName] – v[ProductVersion]]

"ProductName"="[ProductName]"

"ProductVersion"="[ProductVersion]"

"BlocksRemaining"="[PrimaryVolumeSpaceRemaining]"

"InstalledBy"="[LogonUser]"

"InstalledFrom"="[OriginalDatabase]"

"InstalledOn"="[Date] – [Time]"

"ProductVersion"="[ProductVersion]"

"Workstation"="[ComputerName]"

"ProductCode"="[ProductCode]"

"Transforms"="[TRANSFORMS]"

You may have other ideas in mind, but these should get you started. Before we wrap up here, there’s just a few more thing I’d like to mention. First, the reason that this transform is a generic transform is because it’s not ‘keyed’ or linked to our .MSI package. You can check this out for yourself by going to ProjectàSettings. The bottom half of the subsequent dialog is labeled ‘Validation’. You should see that none of the checkboxes are selected (if by chance any of them are, please unselect them). Since all of the checkboxes are unchecked, Windows Installer won’t verify that the .MSI package matches a specific transform.

Next, you could always use this generic transform as the basis of a transform that is unique to a package. To do this make a copy and probably rename the generic transform and open it within InstallShield. The Open Transform Wizard will prompt you for the name of the .MSI package. Once opened within InstallShield you’re ready to make any further changes—including the creation of a response transform.

At this point, we’ll save the transform and we’re good to go. The following is a sample command line that applies a transform to a Windows Installer package:

Msiexec /I “<PathAndName.msi>” /qn TRANSFORMS=”<PathAndNameofGenericTransform.mst>”

 

Leave a Reply

Your email address will not be published. Required fields are marked *