Introducing Managed Bootstrapper Applications

Heath Stewart

Now that WiX v3.6 has been released, I introduce the managed bootstrapper application (MBA) interoperability layer. It’s been available for a while actually, and if you’ve installed any builds of WiX v3.6, or the Microsoft Visual Studio 11.0 Developer Preview you’ve seen it in action.

While Burn – the WiX bootstrapper engine – and the core bootstrapper application interfaces are native and allow you to develop completely native bootstrapper applications, MBA allows managed code developers to utilize their skills to develop rich interactive setups. WPF designers can also utilize their skills to make the setup UI look great. In fact, both of the setup applications mentioned above are written for WPF and running atop the MBA interop layer.

The MBA interop layer leverages COM interoperability features of the CLR, but without requiring previous registration of the assemblies as COM servers as in previous examples. The MBA interop layer is composed of both a native CLR host and the managed framework. It’s in this native CLR host that the managed framework assembly is loaded and COM interfaces marshaled as in-process pointers. Message passing is not required since the Burn engine is written as a free-threaded component. Once the managed framework assembly is loaded, a class factory will create the actual managed bootstrapper application authored in the configuration file and pass its IBootstrapperApplication interface pointers back to the engine.

Because MBA is managed, the .NET Framework is of course required. A simple native bootstrapper application (BA) written atop wixstdba is used to bootstrap the .NET Framework. When you use the WixBalExtension to author your MBA you define the WixMbaPrereqPackageId WixVariable to reference the package ID of the .NET Framework you want to install.

In the following example the .NET Framework 4.0 will be installed if required.

<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
     xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">
    <Bundle
        Name="Test" 
        Version="1.0.0.0" 
        IconSourceFile="Setup.ico">
        <BootstrapperApplicationRef 
            Id="ManagedBootstrapperApplicationHost">
            <Payload 
                Name="BootstrapperCore.config" 
                SourceFile="$(var.TestUX.TargetDir)\TestUX.BootstrapperCore.config"/>
            <Payload 
                SourceFile="$(var.TestUX.TargetPath)"/>
            <Payload 
                SourceFile="NetfxLicense.rtf"/>
        </BootstrapperApplicationRef>
        <Chain>
            <PackageGroupRef 
                Id="Netfx4Full"/>
            <MsiPackage 
                Compressed="yes" 
                SourceFile="$(var.TestPackage.TargetPath)" 
                Vital="yes">
                <MsiProperty 
                    Name="ARPSYSTEMCOMPONENT" 
                    Value="1"/>
            </MsiPackage>
        </Chain>
    </Bundle>
    <Fragment>
        <WixVariable 
            Id="WixMbaPrereqPackageId" 
            Value="Netfx4Full" />
        <WixVariable 
            Id="WixMbaPrereqLicenseUrl" 
            Value="NetfxLicense.rtf" />
 
        <util:RegistrySearch 
            Root="HKLM" 
            Key="SOFTWARE\Microsoft\Net Framework Setup\NDP\v4\Full" 
            Value="Version" 
            Variable="Netfx4FullVersion" />
        <util:RegistrySearch 
            Root="HKLM" 
            Key="SOFTWARE\Microsoft\Net Framework Setup\NDP\v4\Full" 
            Value="Version" 
            Variable="Netfx4x64FullVersion" 
            Win64="yes" />
 
        <PackageGroup 
            Id="Netfx4Full">
            <ExePackage 
                Id="Netfx4Full" 
                Cache="no" 
                Compressed="no" 
                PerMachine="yes" 
                Permanent="yes" 
                Vital="yes" 
                SourceFile="dotNetFx40_Full_x86_x64.exe"
                DownloadUrl="http://go.microsoft.com/fwlink/?LinkId=164193"
                DetectCondition="Netfx4FullVersion AND (NOT VersionNT64 OR Netfx4x64FullVersion)" />
        </PackageGroup>
    </Fragment>
</Wix>

You can customize this behavior even more. For example, since WPF was introduced in .NET 3.0, WiX supports a syntax similar to <supportedRuntime> in its own <wix.bootstrapper> section group: <supportedFramework>. This allows you to specify which Framework you require, inferring the CLR version.

<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>
    <wix.bootstrapper>
        <supportedFramework version="v4\Client" />
        <supportedFramework version="v3.5" />
        <supportedFramework version="v3.0" />
 
        <!-- Example only. Replace the host/@assemblyName attribute with 
        an assembly that implements BootstrapperApplication. -->
        <host assemblyName="AssemblyWithClassThatInheritsFromBootstrapperApplication" />
    </wix.bootstrapper>
</configuration>

Developers building atop MBA need to only reference the BootstrapperCore.dll assembly in the WiX binaries. We’re working on better documentation, but currently only IntelliSense is included. You can also look at the WiX v3.6 setup UI for an example.

I’ll be talking about the MBA interop layer and MBAs in general over the next few weeks.

0 comments

Discussion is closed.

Feedback usabilla icon