A question I usually get when talking about the Bootstrapper is "can it handle multiple reboots?"  The answer is, of course, yes.

Each package file, or file to be executed/installed as part of the package installation, defines a set of exit codes with an associated action.  So if you need to run foobar.exe to install your application, if it returns exit code 0 then the machine needs a reboot.  Exit code 42 on the other hand may indicate a reboot is needed but the installation is a failure.

Example product.xml snippet from Windows Installer 2.0:

<Command PackageFile="instmsiw.exe"
                     Arguments= ' /q /c:"msiinst /delayrebootq"' 
                     EstimatedInstallSeconds="20" >
         
         <
InstallConditions>
                  <!--
snip -->
         </
InstallConditions>
         
         <
ExitCodes>
                  <
ExitCode Value="0" Result="Success"/>
                  <
ExitCode Value="1641" Result="SuccessReboot"/>
                  <
ExitCode Value="3010" Result="SuccessReboot"/>
                  <
DefaultExitCode Result="Fail" 
                                                   FormatMessageFromSystem="true"
                                                   String="GeneralFailure" />
         </
ExitCodes>
</
Command>

So you see that exit code '0' means everything went OK, while 1641 and 3010 indicates the machine needs a reboot but the installation did succeed.  Any other exit code however indicates a failure.  (I will leave the meaning of "FormatMessageFromSystem" for another blog post :)

Four possible exit code values are Success, SuccessReboot, Failure, and FailureReboot.  The question is however what to do with SuccessReboot?  Do you reboot immediately after the package file was executed?  After the package is done installing?  After all packages?  Etc.  The answer is 'whatever you want'.

The parent XML element for Command is the Commands element, which defines a Reboot property.  This property defines the Bootstrapper's behavior in case a SuccessReboot result is issued.

<Commands Reboot="Defer">

         <
Command PackageFile="instmsiw.exe"
                              Arguments= ' /q /c:"msiinst /delayrebootq"' 
                              EstimatedInstallSeconds="20" >

                  <
InstallConditions>
                           <!--
Snip -->
                  </
InstallConditions>

                  <
ExitCodes>
                           <!--
Snip -->
                  </
ExitCodes>

         </
Command>

</
Commands>

The possible values for Reboot are 'None', 'Defer', 'Immediate', and 'Force'.

A value of None indicates no reboot.  Even if every package file returned success reboot the Bootstrapper does nothing.

A value of Defer means to acknowledge the reboot but don't do it yet.  Hold the reboot until either a reboot is forced or until the end of all Bootstrapper packages are installed.

Immediate means if a reboot is encountered reboot immediately after the current package is finished installing (that is all package files have been executed).

Force means reboot regardless.  Even if Success was returned reboot anyways.  It's good for you!

Once the Bootstrapper sees an opportune time to reboot (Deferred until the after the final package, Immediately after a package, or if Forced) then a prompt comes up asking the user to reboot now or manually reboot later.  Then it adds itself to the HKCU RunOnce key so that the Bootstrapper will be ran again after the reboot to continue or finish the installation.

So there you have it!  If you want to make a package that reboots a bunch, well go right ahead.  The Visual Studio 2005 Generic Bootstrapper can play the game and well.  Until next time, deploy on!