IE9 No-Reboot Setup and the Windows Restart Manager

On Windows 7, Internet Explorer 9 can often be installed without rebooting the system. In cases where a system restart is required, either the system lacks one of the required prerequisites (so IE Setup is forced to install it and reboot) or a running program or service is holding one of Internet Explorer’s binaries and it cannot be unloaded.

As explained on MSDN:

The primary reason software installation and updates require a system restart is that some of the files that are being updated are currently being used by a running application or service. Restart Manager enables all but the critical applications and services to be shut down and restarted. This frees the files that are in use and allows installation operations to complete. It can also eliminate or reduce the number of system restarts that are required to complete an installation or update.

The Internet Explorer 9 Setup program will attempt to close programs that are using IE binaries before installing the updated versions. Programs which have been closed by the installer will be restarted if they fall into one of the following three buckets:

  1. The program is registered to restart via the Windows Restart Manager
  2. The program is listed in the Start Menu’s Startup group
  3. The program is listed in the registry’s \Windows\CurrentVersion\Run keys

Registering to restart with the Windows Restart Manager is a best-practice, and is the ideal way to ensure that your application is cleanly unloaded and reloaded after the upgrade is complete.

One of my utilities, SlickRun, is a program launcher that runs when Windows starts and it loads WinINET.dll. Since this is an IE9-updated binary, the utility is shut down when IE9 installation begins and it is restarted when installation completes.

One of the interesting side-effects of restarting applications in groups #2 and #3 is that they’re restarted by calling CreateProcessWithTokenW. When launched by this API, a newly created process gets put into a new Job Object with blank limit flags. In certain obscure cases, this can cause problems for processes that are later spawned by the restarted SlickRun instance.

The problem is that when a descendent JOB_OBJECT_LIMIT_BREAKAWAY_OK flag is checked, Access Denied is returned because of the blank limit flags inherited from the restarted application’s Job Object. When testing IE9’s no-reboot setup, I observed that after SlickRun restarts, any Google Chrome instances it launches fail to function correctly. Chrome uses job objects to isolate its rendering processes and thus encounters the Access Denied issue.

I resolved this problem by updating SlickRun to use the Restart Manager; RM relies upon the Task Scheduler to restart processes and thus does not encounter the job-object limit.

SlickRun is written in Embarcadero Delphi and it now uses the following code to call the RegisterApplicationRestart function. I pass the RESTART_NO_REBOOT flag to ensure that SlickRun is restarted in the event of a crash or a software update, but not after a reboot, since the utility is already registered to start when Windows boots.

 type TPKernelRegisterApplicationRestart = Function(lpCmdLine: PWideChar; dwFlags: DWORD): DWORD; stdcall;


Procedure GetWindowsVersionAndFunctionPointers;
var
  Ver: TOSVERSIONINFO;
  Kernel32Dll: HMODULE;

begin
  Ver.dwOSVersionInfoSize := SizeOf(TOSVERSIONINFO);
  GetVersionEx(Ver);
  WinMajorVersion := Ver.dwMajorVersion;
  WinMinorVersion := Ver.dwMinorVersion;
 
  if (Ver.dwPlatformID = VER_PLATFORM_WIN32_NT) then
    begin
      Kernel32Dll := LoadLibrary('Kernel32.DLL');
      if (0 <> Kernel32Dll) then
        begin
          if (WinMajorVersion > 5) then
          begin
            // Register with the Vista+ Restart Manager
            @RegisterApplicationRestart := GetProcAddress(Kernel32Dll, 'RegisterApplicationRestart');
            if @RegisterApplicationRestart <> nil then
            begin
              RegisterApplicationRestart('-restart', 8 {RESTART_NO_REBOOT});
            end;
          end;

      end;
    end;
end;

Similarly, applications that are written in .NET can also register with the Restart Manager like so:

 public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();            
        if ((Environment.OSVersion.Version.Major > 5) && 
            (0 == RegisterApplicationRestart("-restart", RestartFlags.None)))
            MessageBox.Show("Successfully registered for restart");
    }




    
    [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
    static extern uint RegisterApplicationRestart(string pwzCommandLine, RestartFlags dwFlags);


    
    [Flags]
    enum RestartFlags
    {
      None = 0,
      NotOnCrash = 1,
      NotOnHang = 2,
      NotOnPatch = 4,
      NotOnReboot = 8
    }

}

Restart Manager also supports a few other features to enable recovery of applications after a crash. Windows Error Recovery will restart the application after the recovery process completes, if the parameters passed to RegisterApplicationRestart request this behavior, and the recovery APIs enable the application to restore any preserved data.

If you develop an application that loads Internet Explorer binaries, please consider registering with Restart Manager to allow our shared users to have a more seamless update experience. Thank you!

-Eric