Creating a bootstrapper for a VS Shell application
A bootstrapper is a program used to get the system prepared to install an application. Some applications have requirements in order to run properly.
This is the case for a VS Shell application that has the Visual Studio 2008 Shell Isolated Mode Redistributable package as a requirement.
Basically we need a bootstrapper that installs the Visual Studio 2008 Shell Isolated Mode Redistributable package first and if everything went fine, it redirects the call to our VS Shell application installer.
.Net Framework 2.0 includes the GenerateBootstrapper class to support the ClickOnce scenario. Of course we can use it in other scenarios, since this class is a msbuild task that can be easily added to our msbuild project.
The bootstrapper infrastructure that comes with .Net Fx 2.0 is generic and configurable by the notion of bootstrapper packages.
Bootstrapper packages are composed of one xml file (metadata that describes the package), a xml localization file and the msi/exe for the package itself.
These packages need to be copied to a certain location to be found by Visual Studio and the msbuild infrastructure.
We can see the installed packages on our system from Visual Studio with the Prerequisites... button:
This list is being populated from the %Program Files%\Microsoft SDKs\Windows\v6.0A\Bootstrapper\Packages directory.
The first thing that we need to do is create the package for the VS Shell Redist.
These are two sample xml files for the bootstrapper package:
Product.xml
<?xml version="1.0" encoding="utf-8"?>
<Product ProductCode="Vs.Shell" xmlns="http://schemas.microsoft.com/developer/2004/01/bootstrapper">
<PackageFiles CopyAllPackageFiles="false">
<PackageFile Name="vs_shell_isolated.enu.exe" />
</PackageFiles>
<InstallChecks>
<RegistryCheck Property="VisualStudio" Key="HKLM\Software\Microsoft\VisualStudio\9.0" Value="ApplicationId" />
</InstallChecks>
<Commands Reboot="Immediate">
<Command PackageFile="vs_shell_isolated.enu.exe" Arguments="/q" EstimatedInstallSeconds="2800">
<InstallConditions>
<BypassIf Property="VisualStudio" Compare="ValueEqualTo" Value="VisualStudio" />
</InstallConditions>
<ExitCodes>
<ExitCode Value="0" Result="Success"/>
<ExitCode Value="1641" Result="SuccessReboot"/>
<ExitCode Value="3010" Result="SuccessReboot"/>
<DefaultExitCode Result="Fail" String="GeneralFailure" FormatMessageFromSystem="true" />
</ExitCodes>
</Command>
</Commands>
</Product>
Package.xml
<?xml version="1.0" encoding="utf-8"?>
<Package Name="Vs.Shell" Culture="Culture" xmlns="http://schemas.microsoft.com/developer/2004/01/bootstrapper">
<Strings>
<String Name="Culture">en</String>
<String Name="DisplayName">Vs Shell</String>
<String Name="GeneralFailure">A fatal error occurred. The installation failed.</String>
</Strings>
</Package>
Once we have the package created and correctly installed we can create a simple msbuild proj file that includes the GenerateBootstrapper task:
<Project DefaultTargets="Bootstrapper" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<BootstrapperFile Include="Vs.Shell">
<ProductName>Vs Shell</ProductName>
</BootstrapperFile>
</ItemGroup>
<Target Name="Bootstrapper">
<GenerateBootstrapper
ApplicationFile="MyVSShellApplication.msi"
ApplicationName="My Application"
BootstrapperItems="@(BootstrapperFile)"
OutputPath=".\"
CopyComponents="true"
ComponentsLocation="Relative"
Culture="en"
/>
</Target>
<Import Project="$(MSBuildBinPath)\Microsoft.Common.targets" />
</Project>
So far so good, but now we have three files (bootstrapper (setup.exe), Vs Shell redist exe and our application msi).
We need to package these three files on single setup exe file that the user will download.
To package the files we can use the Microsoft IExpress technology.
And here is where we need to do some *ugly* hacks because of a directory structure problem with the GenerateBootstrapper task and IExpress (it doesn't support adding directory structures)
After we compile our msbuild proj file a directory structure is created similar to:
- Vs Shell
- vs_shell_isolated.enu.exe
- Setup.exe
- MyVSShellApplication.msi
Unfortunately, the MSBuild task doesn't provide the option to have the configuration resource use prerequisite installers found in the target directory, so you must manually update the appropriate resource file to remove the hard-coded path that looks for prerequisites in a sub-directory of the same name.
- Open the Setup.exe program in Visual Studio's resource editor
- Double-click the resource named, SETUPCFG in the 41 folder
- Search for the "Vs Shell\" string and delete the two occurrences that appear
- Save the resource file and the Setup.exe executable will be updated automatically
- Run iexpress
- Create a new package by following the IExpress wizard's steps and make sure to include the following files:
- The MyVSShellApplication.msi file
- The Setup.exe bootstrapper file
- The vs_shell_isolated.enu.exe file
Links:
Bootstrapper manifest generator:
http://www.codeplex.com/bmg
Packages documentation:
http://msdn2.microsoft.com/en-us/library/aa730839(vs.80).aspx
http://blogs.msdn.com/chrsmith/archive/2005/09/02/Rebooting-in-the-Bootstrapper.aspx
IExpress documentation:
http://www.microsoft.com/technet/prodtechnol/ie/ieak/techinfo/deploy/60/en/iexpress.mspx?mfr=true
Happy VS Shell bootstrapping,
Pablo