I've added WiX to my build process to automate the production of windows installer packages for my product. I'm not very proficient with Windows Installer technology, so I thought I might get by with what I've seen is already a "traditional" approach: dark an MSI created by a Visual Studio Setup Project. Well, I knew that this was not the right approach the moment I laid eyes on the script file I got from the decompiler.
However, it was sufficient to familiarize myself with the general structure of a WiX script. Soon after I decided to drop that script and start fresh. After a few dead-ends (that's when I used to refer to the Windows Installer SDK) I got my script working.
My thoughts on the subject are:
Using Managed Custom Actions with WiX
Incorporating managed Custom Actions in WiX is a relatively simple task. However, you have to pay attention to a few details to avoid ending up with a headache just trying to figure out what's wrong with the script.
The first thing I did was making sure that the installer class was in the package, so I added a file reference for the assembly with the installer type.
1: <File Id="InstallerFile" Name="SAMPLE~1.DLL" LongName="SampleInstaller.dll" src="$(var.BinFolder)\SampleInstaller.dll" Vital="yes" KeyPath="yes" DiskId="1" />
What's worth noting here is the specific Id for the file. I did this because it was necessary to reference that specific file later in the script, otherwise I just stuck with the Ids I got from tallow (for the rest of the files in the package).
To setup WiX to execute a managed installer class as a Custom Action, I used 'InstallUtil'. This tool can be run from the command-line ('installutil.exe'), but what I really wanted to use was 'InstallUtilLib.dll'. In order to do this I added the following reference to the script:
1: <Binary Id="InstallUtil" src='$(var.BinFolder)\Installer Assemblies\InstallUtilLib.dll' />
If you've ever darked (decompiler in the WiX toolset) a VS Setup Project that uses managed custom actions, you're probably familiar with the following script entries:
1: <Binary Id="VSDNETCFG" src="Binary\VSDNETCFG.ibd" />
This entry is used to produce a variable that is passed as part of the command-line arguments of installutillib. The variable is [VSDFxConfigFile] in the darked script.
Upon close inspection this embedded file (VSDNETCFG.ibd) is a simple config file that provides run-time binding information. So, I just added it to the installation package:
1: <File Id="ConfigFile" Name="SAMPLE~2.XML" LongName="SampleInstaller.dll.config" src="$(var.BinFolder)\SampleInstaller.dll.config" Vital="yes" DiskId="1" />
Setting up the Custom Action is simple, albeit not trivial. The Custom Actions are calls to installutillib. My advice is to always check these using "InstallUtil.exe" via the command-line, to make sure they're working ok.
1: <CustomAction Id='Uninstall' BinaryKey='InstallUtil' DllEntry='ManagedInstall' Execute='deferred' />
2: <CustomAction Id='UninstallSetProp' Property='Uninstall' Value=' /installtype=notransaction /action=uninstall /LogFile= "[#InstallerFile]" "[#ConfigFile]"' />
3:
4: <CustomAction Id='Install' BinaryKey='InstallUtil' DllEntry='ManagedInstall' Execute='deferred' />
5: <CustomAction Id='InstallSetProp' Property='Install' Value=' /installtype=notransaction /action=install /LogFile= /BinDir="[TARGETDIR]\" /Package="[ProductName]" "[#InstallerFile]" "[#ConfigFile]"' />
6:
7: <CustomAction Id='Rollback' BinaryKey='InstallUtil' DllEntry='ManagedInstall' Execute='rollback' />
8: <CustomAction Id='RollbackSetProp' Property='Rollback' Value=' /installtype=notransaction /action=rollback /LogFile= "[#InstallerFile]" "[#ConfigFile]"' />
9:
10: <CustomAction Id='Commit' BinaryKey='InstallUtil' DllEntry='ManagedInstall' Execute='commit' />
11: <CustomAction Id='CommitSetProp' Property='Commit' Value=' /installtype=notransaction /action=commit /LogFile= "[#InstallerFile]" "[#ConfigFile]"' />
There are a few particulars to note in the script fragment above:
InstallUtilLib.dll: Unknown error in CorBindToRuntimeHost (0x80131700).
System.IO.FileNotFoundException: File or assembly name <assembly>, or one of its dependencies, was not found.
After defining the Custom Actions all that's left is to sequence them in InstallExecuteSequence:
1: <Custom Action="InstallSetProp" After="StartServices">$SampleComponent>2</Custom>
2: <Custom Action="Install" After="InstallSetProp">$SampleComponent>2</Custom>
4: <Custom Action="UninstallSetProp" After="MsiUnpublishAssemblies">$SampleComponent=2</Custom>
5: <Custom Action="Uninstall" After="UninstallSetProp">$SampleComponent=2</Custom>
7: <Custom Action="CommitSetProp" After="Rollback">$SampleComponent>2</Custom>
8: <Custom Action="Commit" After="CommitSetProp">$SampleComponent>2</Custom>
10: <Custom Action="RollbackSetProp" After="Install">$SampleComponent>2</Custom>
11: <Custom Action="Rollback" After="RollbackSetProp">$SampleComponent>2</Custom>
In the end I was surprised at how simple, compact and clean I got my script, especially when compared to the one I got from dark. On another note I have to say that the WiX built-in Custom Actions were a huge help.
PingBack from http://feeds.maxblog.eu/item_1261213.html