From MSI to WiX, Part 7 - Customizing installation using Transforms
The main page for the series is here.
Introduction
In previous blog we were using custom tables to store the data for different environments. Now, we will be using transforms to customize installation. In order to create a Transform we need a base installation database and extended installation database. Transform is the difference between base and extended installation databases.
Creating Base Installation Database
First, we need to create a Base installation which does not any customization data. Here is modified source Wix file from previous blog:
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="https://schemas.microsoft.com/wix/2003/01/wi">
<Product Id="{1EFFDCD2-4B4B-439E-8296-651795EE02D9}"
Name="Minimal Windows Installer Sample"
Language="1033"
Codepage="1252"
Version="1.0.0"
Manufacturer="Acme Corporation"
UpgradeCode="{15F9543C-1C8D-45D6-B587-86E65F914F20}">
<Package Id="{????????-????-????-????-????????????}"
Description="Minimal Windows Installer Sample"
Comments="This installer database contains the logic and data required to install Minimal Windows Installer Sample."
InstallerVersion="200"
Languages="1033"
SummaryCodepage="1252"
Platforms="Intel"
ReadOnly="no"
Compressed="yes"
AdminImage="no"
Keywords="Installer"
ShortNames ="no"
Manufacturer="Acme Corporation" />
<
Media Id="1" Cabinet="CAB001.cab" CompressionLevel="high" EmbedCab="yes" />
<
Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLDIR" Name="Minimal" LongName="MinimalInstallation">
<
Component Id="Component1"
Guid="{A77C5B06-132D-4884-8E17-EA10A83C812D}">
<
File Id="ConsoleApp" DiskId="1" Name="ConsApp.exe" Source="ConsoleApp.exe" Vital="yes" KeyPath="yes" />
<
File Id="ConsoleApp.exe.config" DiskId="1" Name="ConsApp.exc" LongName="ConsoleApp.exe.config"
Vital="yes" Source="ConsoleApp.exe.config" />
<
XmlFile Id="SetKey1"
Action="setValue"
ElementPath="//appSettings/add[\[]@key='Key1'[\]]/@value"
Value="[KEY1]"
File="[INSTALLDIR]ConsoleApp.exe.config" />
<XmlFile Id="SetKey2"
Action="setValue"
ElementPath="//appSettings/add[\[]@key='Key2'[\]]/@value"
Value="[KEY2]"
File="[INSTALLDIR]ConsoleApp.exe.config" />
<XmlFile Id="SetKey3"
Action="setValue"
ElementPath="//appSettings/add[\[]@key='Key3'[\]]/@value"
Value="[KEY3]"
File="[INSTALLDIR]ConsoleApp.exe.config" />
</
Component>
</
Directory>
</Directory>
</Directory>
<
Feature Id="Feature1"
Title="Feature1 title"
Description="Feature1 description"
Level="1"
ConfigurableDirectory="INSTALLDIR" >
<ComponentRef Id="Component1" />
</Feature>
</
Product>
</Wix>
Here are commands to build Minimal.msi:
candle.exe Minimal.wxs
light.exe -out Minimal.msi Minimal.wixobj
Creating extended database using Orca
Create a copy of Minimal.msi and rename it to MinimalTest.msi. This will be our extended installation database for the test environment. Open MinimalTest.msi using Orca, click on Property table in the Tables window on the left. Add three new properties to the Property table:
Property | Value |
---|---|
KEY1 | Test1 |
KEY2 | Test2 |
KEY3 | Test3 |
Save the installation database.
Now we need to generate a transform which will have just the difference between bae and extended database. To do that, we need to run this command (MsiTran.exe will be installed on your machine if you installed the Platform SDK/Windows Installer SDK):
MsiTran -g Minimal.msi MinimalTest.msi Test.mst
To install the product use this command:
msiexec /i Minimal.msi TRANSFORMS=Test.mst
Same procedure should be executed for any additional environment.
Automating the process of creating transforms
We can use Windows Installer Automation Interface to automate the process of cretaing transforms. Here is the script which creates both Test.mst and Dev.mst:
Option Explicit
Const msiOpenDatabaseModeReadOnly = 0
Const msiOpenDatabaseModeTransact = 1
Const msiViewModifyAssign = 3
Const msiTransformErrorNone = 0
Const msiTransformValidationNone = 0
On Error Resume Next
Dim installer : Set installer = Nothing
Dim Devs
Set Devs = CreateObject("Scripting.Dictionary")
Devs.Add "KEY1", "Dev1"
Devs.Add "KEY2", "Dev2"
Devs.Add "KEY3", "Dev3"
CreateTransform "Dev", Devs
Dim Test
Set Test = CreateObject("Scripting.Dictionary")
Test.Add "KEY1", "Test1"
Test.Add "KEY2", "Test2"
Test.Add "KEY3", "Test3"
CreateTransform "Test", Test
Wscript.Quit 0
Sub CreateTransform(TransformName, Values)
' Create a copy of base database
Dim fso
Set fso = CreateObject("Scripting.FileSystemObject") : CheckError
fso.CopyFile "Minimal.msi", TransformName & ".msi" : CheckError
Set fso = Nothing
' Add additional properties to the copy
Dim database
Dim view
Dim record
Set installer = Wscript.CreateObject("WindowsInstaller.Installer") : CheckError
Set database = installer.OpenDatabase(TransformName & ".msi", msiOpenDatabaseModeTransact) : CheckError
Set view = database.OpenView("SELECT `Property`,`Value` FROM Property") : CheckError
view.Execute : CheckError
Dim keys : keys = Values.Keys
dim items : items = Values.Items
Dim i
For i = 0 To Values.Count - 1
Set record = installer.CreateRecord(2)
record.StringData(1) = keys(i)
record.StringData(2) = items(i)
view.Modify msiViewModifyAssign, record : CheckError
Next
view.Close
Set view = Nothing
database.Commit : CheckError
Set database = Nothing
' Create a Transform
Dim database1 : Set database1 = installer.OpenDatabase("Minimal.msi", msiOpenDatabaseModeReadOnly) : CheckError
Dim database2 : Set database2 = installer.OpenDatabase(TransformName & ".msi", msiOpenDatabaseModeReadOnly) : CheckError
Dim transform : transform = TransformName & ".mst"
database2.GenerateTransform database1, transform : CheckError
database2.CreateTransformSummaryInfo database1, transform, msiTransformErrorNone, msiTransformValidationNone : CheckError
Set database1 = Nothing
Set database2 = Nothing
Set installer = Nothing
End Sub
Sub CheckError
If Err = 0 Then Exit Sub
Dim message, errRec
message = Err.Source & " " & Hex(Err) & ": " & Err.Description
If Not installer Is Nothing Then
Set errRec = installer.LastErrorRecord
If Not errRec Is Nothing Then message = message & vbNewLine & errRec.FormatText
End If
Wscript.Echo message
Wscript.Quit 2
End Sub
Embedding Transforms into installer database
Instead of shipping installer database and a separate transform file to a customer we can embed the Transform to an installer database and ship just one file. In fact, we can embed multiple transforms in the database. Here is the fragment of updated version of Transforms generating script from previous section:
' Create a Transform
Dim database1 : Set database1 = installer.OpenDatabase("Minimal.msi", msiOpenDatabaseModeReadOnly) : CheckError
Dim database2 : Set database2 = installer.OpenDatabase(TransformName & ".msi", msiOpenDatabaseModeReadOnly) : CheckError
Dim transform : transform = TransformName & ".mst"
database2.GenerateTransform database1, transform : CheckError
database2.CreateTransformSummaryInfo database1, transform, msiTransformErrorNone, msiTransformValidationNone : CheckError
Set database1 = Nothing
Set database2 = Nothing
' Embed Transform into the database
Set database = installer.OpenDatabase("Minimal.msi", msiOpenDatabaseModeTransact) : CheckError
Set view = database.OpenView("SELECT `Name`,`Data` FROM _Storages") : CheckError
view.Execute : CheckError
Set record = installer.CreateRecord(2)
record.StringData(1) = TransformName
record.SetStream 2, TransformName & ".mst" : CheckError
view.Modify msiViewModifyAssign, record : CheckError
database.Commit : CheckError
Set database = Nothing
The command line to install the product applying the Transform will look like this:
msiexec /i Minimal.msi TRANSFORMS=:Dev
or
msiexec /i Minimal.msi TRANSFORMS=:Test
Comments
Anonymous
March 11, 2008
PingBack from http://ozgrant.com/2008/03/11/customising-your-wix-msi-with-transform-files/Anonymous
October 08, 2008
Hi sir, I have a question?I have to create a msi which is having a same product but having three button through which we can install three separate instance of same product.The product contains three windows service one asp web project one windows utility.Could you please help me for making this successful. Thanks.Anonymous
October 08, 2008
Hi sir, I have a question?I have to create a msi which is having a same product but having three button through which we can install three separate instance of same product.The product contains three windows service one asp web project one windows utility.Could you please help me for making this successful.Anonymous
June 07, 2010
Hi, Is there a wix 2.0 tool to create the transforms? I see that torch tool does the work in Wix 3.0, but I want to see if it can be done with Wix 2.0 tools. -Pratap.