innosetup and .NET 4.0

My simple timesheet software, Timesheets Lite is a a C# program based on Winforms and the DXperience library for WinForms. It is installed with an innosetup script. Up until yesterday the software required the .NET 2.0 library and the installer could detect if .NET 2.0 was installed and download and install it if it wasn’t. Windows 8 was an exception to this rule as .NET 2.0 (actually .NET 3.5) is a Windows feature that needs to be enabled rather than something that needed to be installed. This wasn’t too difficult to get around because you (used) to be able to use DISM to enable Windows features.

Previously my innosetup script detected if Windows 8 was the target OS and then could simply enable the .NET 3.5 feature using this:

Exec('Dism', ' /online /enable-feature /featurename:NetFx3 /All /NoRestart', '', SW_SHOW, ewWaitUntilTerminated, ResultCode);

This had worked fine previously because Windows went away (presumably to the Windows Update site) and downloaded what it needed from there. But it doesn’t work any longer and to get DISM to enable .NET 3.5 the /source parameter must be specified pointing to a local copy of the Windows 8 installation media or an ISO. Clearly this isn’t acceptable for my purposes. Hence I decided to update Timesheets Lite to require the .NET 4.0 library (which is installed on W8 by default). This threw up some other problems though because now I needed to detect .NET 4.0 on earlier versions of Windows, and download and install it during the Timesheets Lite installation process.

This was (surprisingly) easy. I made use of the innosetup .NET detection function from this page and modified the inno script I’d written years ago to download and install .NET 2.0. Here’s some code from my innosetup script for giggles. Firstly, the InitializeSetup function which determines what version of Windows is the target and uses the IsDotNetDetected function to check for the .NET 4.0 client or full installation.

function InitializeSetup(): Boolean;
begin
    dotNetNeeded := false;
    Windows8 := false;
    Result := true;

    if (Version.Major=6) and (Version.Minor=2) then
      begin
        Windows8:=true;

      end;


    if (not IsDotNetDetected('v4\Client', 0)) and (not Windows8) then 
      begin
        if not IsDotNetDetected('v4\Full', 0) then
          begin
              dotNetNeeded := true;
          end
      end 

     if dotNetNeeded then
      begin
            if (not IsAdminLoggedOn()) then
                begin
                    MsgBox('This program needs the Microsoft .NET 4.0 Framework to be installed by an Administrator', mbInformation, MB_OK);
                    Result := false;
                end
            else
                begin

                    
                    dotnetRedistPath := ExpandConstant('{src}\dotnetfx.exe');
                    if not FileExists(dotnetRedistPath) then
                        begin
                            dotnetRedistPath := ExpandConstant('{tmp}\dotnetfx.exe');
                            if not FileExists(dotnetRedistPath) then
                                begin
                                    isxdl_AddFile(dotnetRedistURL, dotnetRedistPath);
                                    downloadNeeded := true;
                                end
                        end

                    SetIniString('install', 'dotnetRedist', dotnetRedistPath, ExpandConstant('{tmp}\dep.ini'));
                end
      end
end;

Next up I’ve added some code to the NextButtonClick function that runs when the current page is wpReady (read to install).


  dotnetRedistURL = 'http://download.microsoft.com/download/9/5/A/95A9616B-7A37-4AF6-BC36-D6EA96C8DAAE/dotNetFx40_Full_x86_x64.exe';

function NextButtonClick(CurPage: Integer): Boolean;

var
  hWnd: Integer;


begin

  Result := true;

  //*********************************************************************************            
  // Only run this at the "Ready To Install" wizard page.
  //*********************************************************************************
  if CurPage = wpReady then
    begin

        hWnd := StrToInt(ExpandConstant('{wizardhwnd}'));


        // don't try to init isxdl if it's not needed because it will error on < ie 3

        //*********************************************************************************
        // Download the .NET 4.0 redistribution file.
        //*********************************************************************************
        if downloadNeeded and (dotNetNeeded = true) and Windows8 = false then
            begin
                isxdl_SetOption('label', 'Downloading Microsoft .NET Framework 4.0');
                isxdl_SetOption('description', 'This program needs to install the Microsoft .NET Framework 4.0. Please wait while Setup is downloading extra files to your computer.');
                if isxdl_DownloadFiles(hWnd) = 0 then Result := false;
            end;

        //*********************************************************************************
        // Run the install file for .NET Framework 4.0. This is usually dotnetfx.exe
        //*********************************************************************************
            if ((dotNetNeeded = true)) then
            begin

                if Exec(ExpandConstant(dotnetRedistPath), '', '', SW_SHOW, ewWaitUntilTerminated, ResultCode) then
                    begin

                        // handle success if necessary; ResultCode contains the exit code
                        if not (ResultCode = 0) then
                            begin

                                Result := false;

                            end
                    end
                    else
                        begin

                            // handle failure if necessary; ResultCode contains the error code
                            Result := false;

                        end;
            end;


    end;

end;

I tested this script on XP, Vista, Windows 7 and Windows 8 and it works very well. The .NET 4.0 download is about 50MB so it’s not too big an impost for users. And I suspect most people will have .NET 4.0 installed anyway. Note that you’ll have to to be using the isxdl innosetup plugin for this installation procedure to work.

This entry was posted in Software on by .

About markn

Mark is the owner and founder of Timesheets MTS Software, an mISV that develops and markets employee timesheet and time clock software. He's also a mechanical engineer, father of four, and a lifelong lover of gadgets.