InnoSetup Installer
Detected .NET Framework

Source: Using InnoSetup with the DotNet Framework (script)

Using Inno Setup with the .NET Framework

This article describes the script used to automatically download and install the Microsoft .NET Framework during the TimeSprite installation. Developers of .NET applications may find this information useful for their own applications.

The script is based heavily on the script Ted Ehrich posted to the Inno Setup newsgroup in this post: http://news.jrsoftware.org/news/innosetup.isx/msg06108.html

The script uses some of the third party add-ons to Innosetup, I think the QuickStart Pack includes what you need.

Requirements

Having the .NET Framework as a dependency makes the installation requirements somewhat complex.

The Script

The script that I ended up with performs the following processing:

I haven’t programmed in Pascal, and this was my first shot at an Inno Setup script, so there are probably plenty of opportunities for tidying things up. A lot of what I did was just copying and modifying stuff. However the end result does seem to handle the .NET installation nicely.

Here is the script: dotnet.iss

Notes:

Unrelated but perhaps useful information

I also have a digital photo program, Picnam, which I converted to the same process. Picnam adds entries to the “Open With” menu in Explorer, so that people can easily open images using Picnam but existing file associations are not affected.

These are the registry entries I used:

[Registry]
Root: HKCR; Subkey: “.jpg\OpenWithList\MyApp.exe”; Flags: uninsdeletekey noerror
Root: HKCR; Subkey: “.jpeg\OpenWithList\MyApp.exe”; Flags: uninsdeletekey noerror
Root: HKCR; Subkey: “applications\MyApp.exe\shell\open\command”; ValueType: string; 
    ValueData: “”"{app}\MyApp.exe”" “”%1″”"; Flags: uninsdeletekey noerror

Root: HKCU; Subkey: "Software\Classes\.jpg\OpenWithList\MyApp.exe"; Flags: uninsdeletekey
Root: HKCU; Subkey: "Software\Classes\.jpeg\OpenWithList\MyApp.exe"; Flags: uninsdeletekey
Root: HKCU; Subkey: "Software\Classes\applications\MyApp.exe\shell\open\command"; 
    ValueType: string; ValueData: """{app}\MyApp.exe"" ""%1"""; Flags: uninsdeletekey

The HKCR values install the “Open With” option for all users, but fail if the user is not an administrator. The HKCU values install it for the current user, and work even if the user is not an administrator.

VMWare

I used VMWare Workstation for the first time in testing the setup process, and I have to say it is a huge productivity booster for this type of thing. Using snapshots I was able to run the installation process with minor changes in various configurations over and over again - probably about 20 times in a couple of hours. It was a huge productivity gain, and I join those who say that VMWare or an equivalent product is an essential tool for software development.

Script:

[_ISTool]
EnableISX=true
 
[Setup]
AppName=MyApp
AppVerName=MyApp 1.0.0
MinVersion=4.1,4.0
DefaultDirName={pf}\MyApp
DefaultGroupName=MyApp
UninstallDisplayIcon={app}\MyApp.exe
Compression=lzma
SolidCompression=true
OutputBaseFilename=MyAppSetup
 
[Files]
Source: c:\ISSI\include\isxdl\isxdl.dll; Flags: dontcopy
Source: Release\MyApp.exe; DestDir: {app}
 
[Messages]
WinVersionTooLowError=MyApp requires Windows NT4, Windows 98 or later.
 
[Icons]
Name: {group}\MyApp; Filename: {app}\MyApp.exe
Name: {group}\Uninstall MyApp; Filename: {uninstallexe}
 
[Code]
var
  dotnetRedistPath: string;
  downloadNeeded: boolean;
  dotNetNeeded: boolean;
  memoDependenciesNeeded: string;
 
procedure isxdl_AddFile(URL, Filename: PChar);
external 'isxdl_AddFile@files:isxdl.dll stdcall';
function isxdl_DownloadFiles(hWnd: Integer): Integer;
external 'isxdl_DownloadFiles@files:isxdl.dll stdcall';
function isxdl_SetOption(Option, Value: PChar): Integer;
external 'isxdl_SetOption@files:isxdl.dll stdcall';
 
const
  dotnetRedistURL = 'http://download.microsoft.com/download/a/a/c/aac39226-8825-44ce-90e3-bf8203e74006/dotnetfx.exe';
  // local system for testing...	
  // dotnetRedistURL = 'http://192.168.1.1/dotnetfx.exe';
 
function InitializeSetup(): Boolean;
begin
  Result := true;
  dotNetNeeded := false;
 
  // Check for required netfx installation
  if (not RegKeyExists(HKLM, 'Software\Microsoft\.NETFramework\policy\v1.1')) then begin
    dotNetNeeded := true;
    if (not IsAdminLoggedOn()) then begin
      MsgBox('MyApp needs the Microsoft .NET Framework to be installed by an Administrator', mbInformation, MB_OK);
      Result := false;
    end else begin
      memoDependenciesNeeded := memoDependenciesNeeded + '      .NET Framework' #13;
      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;
 
function NextButtonClick(CurPage: Integer): Boolean;
var
  hWnd: Integer;
  ResultCode: Integer;
 
begin
  Result := true;
 
  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
    if downloadNeeded then begin
 
      isxdl_SetOption('label', 'Downloading Microsoft .NET Framework');
      isxdl_SetOption('description', 'MyApp needs to install the Microsoft .NET Framework. '+ 
           'Please wait while Setup is downloading extra files to your computer.');
      if isxdl_DownloadFiles(hWnd) = 0 then Result := false;
    end;
    if (Result = true) and (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;
 
function UpdateReadyMemo(Space, NewLine, MemoUserInfoInfo, MemoDirInfo, MemoTypeInfo, 
    MemoComponentsInfo, MemoGroupInfo, MemoTasksInfo: String): String;
var
  s: string;
 
begin
  if memoDependenciesNeeded <> '' then begin
    s := s + 'Dependencies to install:' + NewLine + memoDependenciesNeeded + NewLine;
  end;
  s := s + MemoDirInfo + NewLine + NewLine;
 
  Result := s
end;
Detecting .NET 4.0 Framework & Installing It If Missing

Method 1

Source: http://www.vbforums.com/showthread.php?t=620221

[CustomMessages]
dotnetmissing=This application requires Microsoft Framework 4.0 which is not yet installed on this computer. Would you like to download it now?
 
. . .
 
[Code]
function InitializeSetup(): Boolean;
var
  ErrorCode: Integer;
  netFrameWorkInstalled : Boolean;
  isInstalled: Cardinal;
begin
  result := true;
 
  // Check for the .Net 4.0 framework
  isInstalled := 0;
  netFrameworkInstalled := RegQueryDWordValue(HKLM, 'SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\client', 'Install', isInstalled);
  if ((netFrameworkInstalled) and (isInstalled <> 1)) then begin
    netFrameworkInstalled := false;
  end;
 
  if netFrameworkInstalled = false then begin
    if (MsgBox(ExpandConstant('{cm:dotnetmissing}'), mbConfirmation, MB_YESNO) = idYes) then
    begin
      ShellExec('open',
         'http://www.microsoft.com/downloads/details.aspx?familyid=9CFB2D51-5FF4-4491-B0E5-B386F32C0992&displaylang=en',
         '','',SW_SHOWNORMAL,ewNoWait,ErrorCode);
    end;
    result := false;
  end;
 
end;

Method 2

Source: http://www.vbforums.com/showthread.php?t=620221

This code checks, downloads and installs it if needed. Verify the file isxdl.dll (InnoSetup third-party tool) is also deployed.

[CustomMessages]
dotnetfx40_title=.NET Framework 4.0
dotnetfx40_size=48.1 MB
 
. . .
 
[Code]
const
  dotnetfx40_url = 'http://download.microsoft.com/download/9/5/A/95A9616B-7A37-4AF6-BC36-D6EA96C8DAAE/dotNetFx40_Full_x86_x64.exe';
 
procedure dotnetfx40();
var
  version: cardinal;
begin
  RegQueryDWordValue(HKLM, 'Software\Microsoft\NET Framework Setup\NDP\v4\Full', 'Install', version);
  if version <> 1 then begin
    AddProduct('dotNetFx40_Full_x86_x64.exe',
      '/q /norestart',
      CustomMessage('dotnetfx40_title'),
      CustomMessage('dotnetfx40_size'),
      dotnetfx40_url);
  end;
end;
Installer Tips

Restart Computer

When an installer, after its installation, asks to restart the computer, you can avoid doing so removing the pertinent pending operations from the following Windows registry value:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\PendingFileRenameOperations

Blue Screen of Death

Issue: A “Blue Screen of Death” shows up when trying to start the installer.

He starts the setup and a a random point it gets killed (not an normal stop)….

We have seen this, too. We work around it by having the customer use msconfig to disable services that are not Microsoft's, plus all Startup programs. Then run the installer, then use msconfig to go back to a Normal startup. Works every time.


How To Do A Clean Boot Using the System Configuration Utility

  1. Click “Start”, click “Run”, type “msconfig” (without the quotation marks), and then click “OK”.
  2. In “System Configuration Utility”, click the “Services” tab, and then click to select the “Hide all Microsoft Services” check box.
  3. Click “Disable All”
  4. Click “Startup” tab.
  5. Click “Disable All”
  6. Click “Apply” then “Close”
  7. Restart computer
  8. Insert the <product> CD and install the program.

When the installation is complete you must restore your computer from a clean boot.

  1. Click “Start”, click “Run”, type “msconfig” (without the quotation marks), and then click “OK”. Note: you can choose to do the following steps or just click “Normal Startup” on the General tab.
  2. In “System Configuration Utility”, click the “Services” tab, and then click “Enable All”
  3. Click “Startup” tab.
  4. Click “Enable” All
  5. Click “Apply” then Close
  6. Restart computer

Hello,

We use InnoSetup for a commercial programm.
With a customer we run in to the following problem.

He starts the setup and at a random point it gets killed (not an normal
stop)….

When I use the /LOG option, the log also just stops at a point and no
closing/stop info of inno setup is logged. Also the temporary created
folders are still there. This suggest that (probably some other process -
aka virusscanner) is killing the installer process…
Plugin: File Downloader IDP

Example:

#include <idp.iss>
 
[Files]
Source: "{tmp}\file1.xyz"; DestDir: "{app}"; Flags: external; ExternalSize: 1048576
Source: "{tmp}\file2.xyz"; DestDir: "{app}"; Flags: external; ExternalSize: 1048576
Source: "{tmp}\file3.xyz"; DestDir: "{app}"; Flags: external; ExternalSize: 1048576
 
[Icons]
Name: "{group}\{cm:UninstallProgram,My Program}"; Filename: "{uninstallexe}"
 
[Code]
procedure InitializeWizard();
begin
    idpAddFileSize('http://127.0.0.1/file1.xyz', ExpandConstant('{tmp}\file1.xyz'), 1048576);
    idpAddFileSize('http://127.0.0.1/file2.xyz', ExpandConstant('{tmp}\file2.xyz'), 1048576);
    idpAddFileSize('http://127.0.0.1/file3.xyz', ExpandConstant('{tmp}\file3.xyz'), 1048576);
 
    idpDownloadAfter(wpReady);
end.