Custom WiX Burn bootstrapper user interface? - wix

I'm creating an installation package with WiX 3.6 primarily so I can take advantage of the Burn bootstrapping features. So far I have several MSI packages bundled together that will be installed with the built-in bootstrapper application (WixStandardBootstrapperApplication.RtfLicense).
I have read that Burn allows the default bootstrapper application to be replaced by specifying a custom UX.dll, but I haven't yet been able to locate any resources that describes how the custom ux.dll is constructed (that is, how it integrates with the Burn engine, what technologies do I use, what interfaces should I implement, etc.).
My goal is to create a branded bootstrapper that can collect arbitrary information from a user and pass that information onto the various bundled MSI files, EXE files, etc.
So I have two questions really:
To what degree is the default bootstrapper application customizable?
Are there any resources available that describe how to construct a custom UX.dll?

The key thing to know is that there is a BootstrapperCore.dll in the WiX binaries that defines a BootstrapperApplication class that handles the integration with the Burn engine. I needed to create my own derived class and override the 'Run' method to launch my custom UI.
It was also helpful to use the WixBA project that defines the UI for the WiX bootstrapper as a reference for using the BootstrapperApplication class (src\Setup\WixBA\WixBA.csproj).
The markup I used to reference my custom bootstrapper DLL file is:
<BootstrapperApplicationRef Id="ManagedBootstrapperApplicationHost" >
<Payload SourceFile="$(var.InstallSourceResources)Bootstrapper\FusionInstallUX.dll"/>
<Payload Id="FusionInstallUX.config"
SourceFile="$(var.InstallSourceResources)Bootstrapper\FusionInstallUX.BootstrapperCore.config"
Name="BootstrapperCore.config" Compressed="yes"/>
</BootstrapperApplicationRef>
The configuration file consists of:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<sectionGroup
name="wix.bootstrapper"
type="Microsoft.Tools.WindowsInstallerXml.Bootstrapper.BootstrapperSectionGroup, BootstrapperCore">
<section
name="host"
type="Microsoft.Tools.WindowsInstallerXml.Bootstrapper.HostSection, BootstrapperCore" />
</sectionGroup>
</configSections>
<startup useLegacyV2RuntimeActivationPolicy="true">
<supportedRuntime version="v4.0" />
</startup>
<wix.bootstrapper>
<host assemblyName="FusionInstallUX">
<supportedFramework version="v4\Full" />
<supportedFramework version="v4\Client" />
</host>
</wix.bootstrapper>
</configuration>
I also followed other examples and appended
[assembly: BootstrapperApplication(typeof([name of class deriving from BootstrapperApplication]))]
to the AssemblyInfo.cs file.
And lastly, Stack Overflow question Specify the INSTALLLOCATION of packages in WiX inside the Burn managed bootstrapper describes how to set and use Burn variables to help drive the installation.
Armed with this information I am now prepared to wreak havoc on the world with my very own custom Bootstrapper application!

To supplement #Bill Campbell's answer, I've written a series of blog posts on writing a custom WiX Bootstrapper in .NET which goes into more depth about the pieces involved, at least for a managed code solution.

Not precisely answer to this question, but if you want to customize appearance of ManagedBootstrapperApplicationHost, then this is what you need to do.
To keep short, you need to declare your variables like this (I put it before BootstrapperApplicationRef)
<WixVariable Id="PreqbaThemeXml" Value="tt.thm" />
<WixVariable Id="PreqbaThemeWxl" Value="tt.wxl" />
assuming tt.thm is your theme file, and tt.wxl is your translation file.
Note those files, as well as all files they reference must be included to BootstrapperApplicationRef as Payoload, like
<Payload SourceFile="tt.wxl"/>
<Payload SourceFile="tt.wxl"/>
<Payload SourceFile="cat.png"/>
As an example of layout you can use mbapreq.thm, found under WiX sources.

In addition to the other resources listed here, a good bare-bones example of a custom bootstrapper application for Burn is Custom WiX Managed Bootstrapper Application.
I found that this is a good place to start with before digging deeper into other more thorough examples like the WixBA project in the WiX sources.

One detail I was missing when setting this up was that I had to include a reference to WixBalExtension.dll. That's because the ManagedBootstrapperApplicationHost is defined in that DLL and used in the bundle like this:
<BootstrapperApplicationRef Id="ManagedBootstrapperApplicationHost">
<Payload Name="BootstrapperCore.config"
SourceFile="MyBA.BootstrapperCore.config" />
<Payload SourceFile="MyBA.dll"/>
</BootstrapperApplicationRef>

Related

WiX standard bootstrapper: launch application after install

I am creating a Bundle installer, using WiX standard bootstrapper in order to install .NET Framework 4.5 (if not yet installed) and my application in the user's computer. The bundle installer also allows the user to set the installation path for the application, and uses WiX standard bootstrapper's UI only (no other installers' interfaces are shown to the user).
Right now I'm struggling to allow the user to launch my application at the end of the installation.
Closest related anwers I could find use a variable named LaunchTarget, which causes WiX standard bootstrapper to display a "Launch" button in the end of the installation.
Given solutions and why I wasn't able to use them follow:
Answer "A" suggests setting the LaunchTarget variable to the exact folder inside "Program Files" folder where the application should be installed. This doesn't work for me, because I want to allow the user to specify the target installation folder (application can be installed outside of the "Program Files" folder).
Answer "B" suggests setting the LaunchTarget variable by using the InstallFolder variable to determine where the user configured the standard bootstrapper to install the software to. This seemed perfect for my case, but after setting the LaunchTarget value simply to "[InstallFolder]" I verified that pressing the "Launch" button in the standard bootstrapper's UI actually opens the folder where the installer is running, and not the folder where the user chose to install the software, as I expected. (is that a bug?)
Question is: how can I correctly set the LaunchTarget variable to the right path, considering that the user can modify the installation folder through WiX standard bootstrapper's UI?
The code for the Bunde follows.
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
xmlns:bal="http://schemas.microsoft.com/wix/BalExtension">
<Bundle Name="My Game Trainer" Manufacturer="MY_MANUFACTURER_ID_HERE" UpgradeCode="MY_GUID_HERE" Version="!(bind.packageVersion.TrainerMsiPackage)" DisableModify="yes">
<Variable Name="LaunchTarget" Value="[InstallFolder]" />
<BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.RtfLargeLicense">
<bal:WixStandardBootstrapperApplication ShowVersion="yes" LicenseFile="PATH_TO_MY_LICENSE.rtf" />
</BootstrapperApplicationRef>
<Chain>
<PackageGroupRef Id="NetFx45Web"/>
<MsiPackage Id="TrainerMsiPackage" SourceFile="$(var.SetupMSI.TargetPath)" DisplayInternalUI="no">
<MsiProperty Name="TRAINER_INSTALL_DIR" Value="[InstallFolder]"/>
</MsiPackage>
</Chain>
</Bundle>
</Wix>
Using WiX Toolset v3.11.1 (+Visual Studio 2017 Extension).

Generating an EXE from MSI in Wix

I'm tring to generate EXE file from MSI in Wix installer, I added a new project (Bootstrapper) but I can specifying the path of my MSI file
<Bundle Name="Bootstrapper" Version="1.0.0.0" Manufacturer="" UpgradeCode="e45fdbb6-192c-46f7-b4db-d04af69edada">
<BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.RtfLicense" />
<Chain>
<!-- TODO: Define the list of chained packages. -->
<MsiPackage SourceFile="WixSetup.msi" />
</Chain>
</Bundle>
Can you help ?
Thanks in advance
Abdulsalam
Add a reference of your msi's wixproj to your bootstrapper application.
You can now reference the msi file like this
<MsiPackage SourceFile="$(var.WixProjName.TargetPath)" />
This will automatically point to the debug location or release location depending on your build mode.
You can see a list of well-defined vars passed to candle.exe in the output when building. You'll see a bunch of defines like "-dWixProjName.Property=Value" and then you can use those values in your bundle xml like so $(var.WixProjName.Property) which will get replaced by the Value before compiling.
You can see a list of the defined properties when you reference another project here: http://wixtoolset.org/documentation/manual/v3/votive/votive_project_references.html

WiX bootstrapper disable .NET Framework installation chaining

In my WiX installer, I do not want .NET installed automatically if it isn't installed. It should just give a warning or merely error out.
The reason to avoid it is explained here:
One HUGE word of
caution here: Because the .Net installer will technically be part of
your install chain, if the user installs .Net but then cancels your
install, your installer will still be listed in the Add/Remove
programs since one if it’s components (the .Net installer) completed.
Tread with caution.
He seems to be intentionally including it. But I'm not and I happened to set <supportedRuntime version="v4.5" /> which I guess isn't a real version (4.5 => 4.0 as far as this is concerned?). My WiX managed bootstrapper application exe automatically prompted me to download and install the "missing" .NET Framework.
For computers that ARE missing 4.0, I don't want this to happen. WiX also complains if I leave out:
<WixVariable Id="WixMbaPrereqLicenseUrl" Value="..." />
<WixVariable Id="WixMbaPrereqPackageId" Value="..." />
in which I literally leave in ... because I don't want it to work anyway.
In this thread, #Shruthi asks
Is there a way to replace the prerequisite .Net install UI with just an notification to the user that they need to install a particular version of .Net before they can install the bundle?
And Rob Mensching replies:
Yes, that is possible now.
... BUT HE DOESN'T ELABORATE. How is it possible now?
Thanks!
===============
In my Bundle's Bootstrap.Config:
<startup useLegacyV2RuntimeActivationPolicy="true">
<supportedRuntime version="v6" /> <!-- Pretending it's the future! -->
</startup>
The Bundle itself does not reference any .NET stuff and does not reference WixNetFxExtension and uses the custom <BootstrapperApplicationRef Id="ManagedBootstrapperApplicationHost" />
To answer how to handle checking for the .Net 4.0 Framework include the WixNetfxExtension in your project
then under product add a reference to the property NETFRAMEWORK40FULL and put a condition on it.
<PropertyRef Id="NETFRAMEWORK40FULL"/>
<Condition Message="This application requires .NET Framework 4.0. Please install the .NET Framework then run this installer again.">
<![CDATA[Installed OR NETFRAMEWORK40FULL]]>
</Condition>
for the chained case again include wixnetfxextension and include NetFx40Redist package group
<PackageGroupRef Id="NetFx40Redist"/>

Burn: Access to msi files inside Bootstrapper.exe

Question: Can we access msi files (and other installers) packed with Burn Bootstrapper at install time?
Let's say if we need to read some property, or apply mst just before starting the installation etc.
Is that possible?
Did you try to add the transform as a payload to your MsiPackage element, and set the TRANSFORMS property using MsiProperty element?
<MsiPackage ...>
<Payload Compressed="yes" SourceFile="c:\mytransform.mst"/>
<MsiProperty Name="TRANSFORMS" Value="mytransform.mst" />
</MsiPackage>
If you really need to get the path to embeded payloads, and if you are using the standard bootstrapper, you are going to need to create a bafunctions.dll and do some C/C++ coding.
To create a bafunctions.dll, first download the wix source code and use the project src\burn\samples\bafunctions as an example. To use the bafunctions.dll you have compiled, add it as a payload to the bootstrapper
<BootstrapperApplicationRef ...>
<Payload Compressed="yes" SourceFile="c:\bafunctions.dll" />
</BootstrapperApplicationRef>
That's enough to make the standard bootstrapper call the bafunctions.dll callbacks. You have callbacks for OnDetect(), OnDetectComplete(), OnPlan(), OnPlanComplete(). You can use these functions to do some non-trivial detections and get/set burn variables.
This post has an example on how to use bafunctions.dll to get the path to an embeded payload at runtime:
How to pass the path to a bundle's payload to an msi?

WiX bootstrapper that only shows the package Dialogs or atleast one that doesn't require the license approval

I have a project that I am creating an installer for. I have the msi created that will do the install but I also need to install some pre-reqs (.NET 4.0 and VSTO client tools or whatever they are called)
From what I can tell I need to use a bootstrapper and while it seems to work I really don't want the default dialogs that make me approve the license. I would like to skip that completely. (If I could hide the bootstrapper that would be fine but just having an "Install" button without the EULA would be ok).
Here is the xml I am currently using.
<?xml version="1.0" encoding="UTF-8"?>
<WixVariable Id="WixStdbaLogo" Value="logo.png" />
<BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.RtfLicense">
</BootstrapperApplicationRef>
<Chain>
<!-- TODO: Define the list of chained packages. -->
<PackageGroupRef Id="NetFx40Web"/>
<MsiPackage SourceFile="TestRibbonLocationInstaller.msi" DisplayInternalUI="yes" />
</Chain>
</Bundle>
So from what I can tell I need to basically create a custom bootstrap application for this that I then reference as the bootstrapperapplication. By doing this I will be able to better control the UI (Basically hide it).
Is this thought process correct?