For some time now, I’ve struggled to work out how to build the WiX files that are generated by MSI Factory in FinalBuilder and include the bootstrapper. Building WiX files in FinalBuilder is dead easy – it has actions for the WiX Candle and the WiX linker so you can compile the files that MSI Factory generates (or any other WiX files of course) quite easily. But once you have your MSI, it is nice to have the EXE wrapper for bootstrapping it. Why does this matter? Because if you issue an update to your MSI file, and then double-click to run it, Windows will tell the user they must manually uninstall the app before they can install the update. Not so friendly.
Okay, so what’s so hard? The bootstrap compiler takes a number of options, and they include the GUIDs that are needed to check if it is installed already. The problem is that you don’t know the GUID in the build. It turns out that the answer is simple, but it took some time to find, so I’m blogging it so I remember for next time.
The MSI Factory software comes with a command line tool called “IRMakeBootstrap.exe”. This takes an XML configuration file and the name of the output file as parameters, and the product name, but also then needs three parameters that are key to proper operation.
The key ones are -var:PackageCode and -var:ProductCode. Now if you look at your WiX file you will see that it has a line like:
<Product Id="D03192D5-40A2-4EAC-B1A1-9BACE96AFE78" Name="My App Name" Version="1.0.0" Manufacturer="My Company" UpgradeCode="76D9BEB2-C077-4B7C-A91E-DF294F4C3457" Language="1033">
The “Id” matches the “Product Code” , and the “UpgradeCode” matches the Upgrade code, in the Project settings dialog of MSI Factory. However, the PackageCode is not in the file at all. There is a Package node in the XML, but no value. If you look in MSI Factories dialog, there is a “Package ID” on the Package tab, but it says “leave blank to auto-generate”. But if that is left blank, I can’t find out what it is to set it to something useful, and thus pass to the bootstrap maker.
Okay, so what is the solution? Simple. Define a GUID in the dialog for the Package ID in the MSI Factory dialog. This is normally a “bad thing”, because you want to to change each time (pretty much essential). But you are doing better anyway by using FinalBuilder (or other build tool?) and FinalBuilder is able to generate a GUID just fine. So, set it to a valid GUID string, and then generate the WiX files.
<Package Id="59D9FCDF-13BE-4AD7-841B-1F11D2E74500" ...
You will now find that the XML contains an “Id” for the package too. Haha! Now you have what you need to automate it. The value in the XML can now be replaced in your script, and also passed through to the bootstrap builder. Note that the GUIDs passed to the bootstrap builder need the curly brackets surrounding them. This ensures that they match properly.
Finally, you can check that it all works properly by running your install EXE with the “/Log:c:\install.txt” parameter which causes it to output a log of its activities.
The final parameters for the bootstrap maker is:
"D:\Src\bootstrap_config.xml" "D:\Src\MySetup.exe" -var:AllowExtractMSI=1 -var:ProductName="Product Name" -var:PackageCode="{%INST_PACKAGECODE%}" -var:ProductCode="{%INST_PRODUCTCODE%}" -var:ProductVersion=%VERSION_MAJOR%.%VERSION_MINOR%.%VERSION_BUILD%