A team mate of mine on the deployment team has just released an internal tool he was using for testing the genericness of our generic bootstrapper to the world on GotDotNet. You can grab it at:

http://www.gotdotnet.com/Community/Workspaces/workspace.aspx?id=ddb4f08c-7d7c-4f44-a009-ea19fc812545

With this tool, you can create an installable package that will show up in Visual Studio 2005 and can be bundled into your setup program. You can use this to wrap any current component or prerequisite installers so out bootstrapper can install them for you automatically. The app will generate all the XML VS will need to build a bootstrapper to run your installers.

Heck, you don't even need VS! With the release of Beta 1, the generation of bootstrappers is available as a standard MSBuild task. With just the SDK and this tool, you can write your own package installers quickly and leverage the work we've done for the generic bootstrapper. With freely available tools, you can make smart bootstrappers quickly and efficiently!

The release of this tool gave me a good idea for a topic to blog about this week: how the bootstrapper takes the XML files and turns them into a setup.exe that does the right thing. My team thought it was a pretty good idea so here we go. (As always, we change things so this is not the gospel forever. I'll try and blog about changes though)

In a previous post, (http://blogs.msdn.com/misampso/archive/2004/03/11/88402.aspx) I talked about the files on disk that the bootstrapper uses. The key files are the product.xml and package.xml files under each component's directory (let's use the word component to mean everything under that subdirectory; we'll be throwing package and product around a lot). The product.xml contains all the language independent stuff and the package.xml has the files specific to a locale. Files that are language specific go along side the package.xml file under the locale directory and language neutral files go next to product.xml.

Now that we've got the packages laid out on disk, let's walk through a build process. Here's the signature for the GenerateBootstrapper task from Microsoft.Common.Targets (available in your framework directory):

<GenerateBootstrapper
Condition="'$(BootstrapperEnabled)'=='true'"
ApplicationFile="$(TargetDeployManifestFileName)"
ApplicationName="$(AssemblyName)"
ApplicationUrl="$(FormattedApplicationUrl)"
BootstrapperItems="@(BootstrapperFile)"
ComponentsUrl="$(FormattedComponentsUrl)"
Culture="$(TargetCulture)"
FallbackCulture="$(FallbackCulture)"
OutputPath="$(PublishDir)"/>

 

Here's an example project snippet that calls this task directly:

<ItemGroup>
<BootstrapperFile Include="Microsoft.Net.Framework.2.0">
<InProject>False</InProject>
<ProductName>.NET Framework 2.0</ProductName>
<Install>true</Install>
</BootstrapperFile>
<BootstrapperFile Include="My.Custom.Package.1.0">
<InProject>False</InProject>
<ProductName>Sampy's Custom Package 1.0</ProductName>
<Install>true</Install>
</BootstrapperFile>
</ItemGroup>

...

<GenerateBootstrapper
BootstrapperItems="@BootstrapperFile"
Culture="en"
OutputPath="c:\myboostrapper"
/>


This will create a bootstrapper that will install the .Net framework and our custom component and then exit. The task will take the data contained in the XML files and burn it into setup.bin in the form of a special config file. Let's walk through that process.

First, the task builds a list of all of the components that are available on disk. It reads in the package and product XML and merges them into a single internal data structure. These are placed in an order dependant list; there is a file called catalog.xml that lives in the component directory that indicates any cross-component dependencies (for example the J# redist depends on the .Net framework redist and the .Net redist depends on 2.0 of the Microsoft Installer). The task re-orders your components to take into account these dependencies so when the final config file is written, the bootstrapper goes about things in the proper order. Now that we've got all your settings and we've set them in the proper order, it's time to build the exe.

We iterate over each component in our list and transform the XML into our config file format. Also, we grab any package files that are specified and either burn them into the exe (for external install checks and EULAs) or copy them to the proper folder in the output directory (everything else). After we've built the config segments for each package we put a header on the file with information about what app to launch when we're done and other component independent data. We stick the config file in the resource stream of the exe and now we're almost there. The final step is to put the strings (and fonts) for the UI into the bootstrapper. This data is found in the setup.xml file in your bootstrapper directory under a locale specific directory. This file allows the setup.bin image to be language independent as well as translatable to any language (just crack open setup.xml and translate away!). Also, you could customize the strings in there if you wanted to.

Now that we've stuffed everything we need into the bootstrapper, we copy it to the output directory and everything is good to go. Is that enough info for all you component authors out there or would more nitty gritty info be helpful?

Happy bootstrapping!