Click here to Skip to main content
Click here to Skip to main content

Modular InnoSetup Dependency Installer

By , 23 Sep 2011
 
Screenshot - dotnetfx_installer1.jpg

Screenshot - dotnetfx_installer3.jpg

Introduction

This article contains a modular InnoSetup install script that downloads (if setup files don't exist already) and installs various dependencies like .NET Framework 1.1/2.0/3.5/4.0 and others on 32-bit or 64-bit Windows.

Background

Once upon a time, I needed an installer for my .NET applications. I knew that I could use the "genius" ClickOnce installer, but in my opinion it has a bad interface and is not very handy. Then I came across a script for InnoSetup that had everything I wanted, but unfortunately it was only for .NET 1.1. So, I spent a few hours (became more over time) in InnoSetup and modified it to my needs.

Details

The source code is written modular. The folder structure looks like this:

Screenshot - dotnetfx_content.jpg

  • setup.iss - contains the basic setup where you include the modules (products) you need. They need to be included at the top like #include "scripts\products\dotnetfx11.iss" and then you only have to call their main function inside the [Code] part like dotnetfx11();
  • bin - contains the final output of the installer
  • src - contains the application files of your program
  • scripts
    • products.iss - contains the shared code for the product scripts. You only have to change the [CustomMessages] part and [Files] part (inclusion of isxdl language files)
    • isxdl - contains the downloader DLL for the setup (if there is something to download) and its language files (e.g. german.ini). This is the place where you can put your language files for the isxdl downloader in.
    • products - contains the scripts for products which are required by the application (e.g. .NET Framework 2.0)
      • dotnetfx11.iss - .NET Framework 1.1
      • dotnetfx11lp.iss - .NET Framework 1.1 Language Pack
      • dotnetfx11sp1.iss - .NET Framework 1.1 + Service Pack 1
      • dotnetfx20.iss - .NET Framework 2.0
      • dotnetfx20lp.iss - .NET Framework 2.0 Language Pack
      • dotnetfx20sp1.iss - .NET Framework 2.0 + Service Pack 1
      • dotnetfx20sp1lp.iss - .NET Framework 2.0 Service Pack 1 Language Pack
      • dotnetfx20sp2.iss - .NET Framework 2.0 + Service Pack 2
      • dotnetfx20sp2lp.iss - .NET Framework 2.0 Service Pack 2 Language Pack
      • dotnetfx35.iss - .NET Framework 3.5
      • dotnetfx35lp.iss - .NET Framework 3.5 Language Pack
      • dotnetfx35sp1.iss - .NET Framework 3.5 + Service Pack 1
      • dotnetfx35sp1lp.iss - .NET Framework 3.5 Service Pack 1 Language Pack
      • dotnetfx40client.iss - .NET Framework 4.0 Client Profile
      • dotnetfx40full.iss - .NET Framework 4.0 Full
      • ie6.iss - Internet Explorer 6
      • iis.iss - Internet Information Services (just a check if it is installed)
      • jet4sp8.iss - Jet 4 + Service Pack 8
      • kb835732.iss - Security Update (KB835732) which is required by .NET Framework 2.0 Service Pack 1 on Windows 2000 Service Pack 4
      • mdac28.iss - Microsoft Data Access Components (MDAC) 2.8
      • msi20.iss - Windows Installer 2.0
      • msi31.iss - Windows Installer 3.1
      • msi45.iss - Windows Installer 4.5
      • sql2005express.iss - SQL Server 2005 Express + Service Pack 3
      • sql2008express.iss - SQL Server 2008 Express R2
      • sqlcompact35sp2.iss - SQL Server Compact 3.5 + Service Pack 2
      • vcredist2010.iss - Visual C++ 2010 Redistributable
      • wic.iss - Windows Imaging Component
      • winversion.iss - helper functions to determine the installed Windows version including service packs
      • fileversion.iss - helper functions to determine the version of a file
      • stringversion.iss - helper functions to correctly parse a version string
      • dotnetfxversion.iss - helper functions to determine the installed .NET Framework version including service packs

Mostly you may have to tweak the setup.iss because of different Windows version / service pack version check depending on the version of .NET Framework you need.

If a dependency (product) is not installed, the script checks if the product's setup exists inside the dependencies directory which is configurable in products.iss. By default it is: .\MyProgramDependencies. If they don't exist there, it tries to download them (except for Windows Service Packs). This means a support for offline installing via CD or DVD is also possible. In the recent versions, there was also support for 32-bit (x86) and 64-bit (x64) OS including Itanium (ia64) added.

Screenshot - dotnetfx_installer2.jpg

Screenshot - dotnetfx_installer4.jpg

The installation routine of the dependencies is automatic, and they run in quiet or semi quiet mode. Therefore no user interaction is needed, except for Internet Explorer 6. This setup script uses [CostumMessages] so that you can easily add multi-language support to your setup and are easily able to configure settings (like the dependencies directory) without looking at the [Code] part.

Applications used for the script are:

  • Inno Setup - setup engine (version 5.4.2)
  • ISTool - extends Inno Setup but I just needed the isxdl.dll downloader (version 5.3.0)

Known Problems

If dependencies are needed, the required free hard drive size is incorrect.

Points of Interest

Special thanks go to Ted Ehrich who created the .NET Framework 1.1 script. Well, I am sure that this script will serve me in the future very well and I hope you may like it too.

History

  • 14 Oct, 2007
    • Initial version
  • 19 Oct, 2007
    • Minor update to code
  • 27 Oct, 2007
    • Minor update to code
  • 25 Jan, 2008
    • Minor update to code
  • 15 Aug, 2008
    • Now uses dotnetchk.exe to determine which version of .NET Framework and its language pack is installed
    • Added .NET Framework language pack(s) to script
    • Added translation for download page
    • Separated script code into multiple files to make it easier to update the script for different versions of the .NET Framework
  • 1 Jan, 2009
    • Wrote source code modular (each dependency now has one file)
    • Added code for Windows security updates, .NET Framework 1.1, 2.0sp1, 3.5, 3.5sp1 and their language packs
    • No more dotnetchk.exe
  • 1 Sep, 2009
    • Code for dependencies installation routine was completely rewritten and is now executed before the actual installation of the application. Setup also checks if all dependencies are installed successfully and if not, displays an error page
    • Added support for 32-bit (x86) and 64-bit (x64) OS including Itanium (ia64)
    • Added code for .NET Framework 2.0 SP2 and its language pack
    • Fixed windows version check bug and language pack check bug
  • 23 Sep, 2011
    • Added support for .NET Framework 4.0, Windows Installer 4.5, Visual C++ 2010 Redistributable, SQL 2008 Express and SQL 3.5 Compact Edition (community)
    • Added helper functions to determine the installed .NET Framework version which removed redundant code
    • Added version strings parser to fix wrong detection for version numbers above 9
    • Added delayed and forced mid-install restart support
    • Added usage of #define in setup.iss (community)
    • Added unicode version of Inno Setup as default for better multilanguage support
    • Fixed restart on 3010 resultcode from installers
    • Fixed missing check in Windows 2000 Security Update (KB835732)
    • Added support for offline files on x64 and IA64 OS

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

stfx
Austria Austria
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralRe: sql compact fails installmemberFreddyvdh8 May '12 - 1:37 
Hi, I have the same problem. The changes don't fix the problem. The downloaded file is a selfextracting file containing two msi-files.
GeneralRe: sql compact fails installmemberse7enth8 May '12 - 4:06 
Try this code
Unfortunately you need to host sql compact by yourself.
 
File: scripts\products\sqlcompact35sp2.iss
[CustomMessages]
sqlcompact35sp2_title=SQL Server Compact 3.5 Service Pack 2
sqlcompact35sp2_titlex64=SQL Server Compact 3.5 Service Pack 2  x64
 
en.sqlcompact35sp2_size=3.0 MB
de.sqlcompact35sp2_size=3.0 MB
en.sqlcompact35sp2_sizex64=3.5 MB
de.sqlcompact35sp2_sizex64=3.5 MB
 

[Code]
const
	sqlcompact35sp2_url = 'http://pliki.naturalmedia.pl/prerequisites/SSCERuntime_x86-ENU.msi';
  sqlcompact35sp2_urlx64 = 'http://pliki.naturalmedia.pl/prerequisites/SSCERuntime_x64-ENU.msi';
 
procedure sqlcompact35sp2();
begin
	if (not IsWin64 and
  not RegKeyExists(HKLM, 'SOFTWARE\Microsoft\Microsoft SQL Server Compact Edition\v3.5\ENU')) then
	   
		AddProduct('SSCERuntime_x86-ENU.msi',
			'/qb',
			CustomMessage('sqlcompact35sp2_title'),
			CustomMessage('sqlcompact35sp2_size'),
			sqlcompact35sp2_url,
	        false, false);
 
 if (IsWin64
    and 
    (
       not RegKeyExists(HKLM, 'SOFTWARE\Microsoft\Microsoft SQL Server Compact Edition\v3.5\ENU')
      and  not RegKeyExists(HKLM, 'Wow6432Node\SOFTWARE\Microsoft\Microsoft SQL Server Compact Edition\v3.5\ENU')
     )) then
	begin
			AddProduct('SSCERuntime_x86-ENU.msi',
			'/qb',
			CustomMessage('sqlcompact35sp2_title'),
			CustomMessage('sqlcompact35sp2_size'),
			sqlcompact35sp2_url,
			false, false);
			AddProduct('SSCERuntime_x64-ENU.msi',
			'/qb',
			CustomMessage('sqlcompact35sp2_titlex64'),
			CustomMessage('sqlcompact35sp2_sizex64'),
			sqlcompact35sp2_urlx64,
			false, false);
  end;
end;
Tomasz Maj

GeneralRe: sql compact fails installmemberFreddyvdh9 May '12 - 3:02 
Thanks Tomasz, it works! I had already thought about such a solution, but with your code I didn't needed to write it myself Wink | ;)
Questionnewer c++ 2010 residistributable package already installedmembermatthias_791 Mar '12 - 22:52 
Hello,
 
I have got the problem that the installer wants to install the c++ 2010
reditributable package and then exits because it recognizes that a newer
version of the package is already installed.
 
That's possible because I have Visual Studio 2010 installed on that machine.
 
But what can I do then ? I cannot install the program.
 
It would be great if your could edit the vcredist2010.iss file that it recognizes
that the package is already installed if its a newer one.
 
Thanks,
Matthias
AnswerRe: newer c++ 2010 residistributable package already installedmemberMember 874435120 Mar '12 - 14:04 
If you look into scripts/products/vcredist2010.iss, I think it should say
 
RegQueryDWordValue(HKLM, 'SOFTWARE\Microsoft\VisualStudio\10.0\VC\VCRedist\' + GetString('x86', 'x64', 'ia64'), 'Installed', version);
 
instead of
 
RegQueryDWordValue(HKLM, 'SOFTWARE\Microsoft\VisualStudio\10.0\VC\VCRedist\' + GetString('x86', 'x64', 'ia64'), 'Install', version);
 
ie. there is no Install value, but there is Installed. That is also consistent with the check for one on the next line
 
	if (version <> 1) then ...

GeneralRe: newer c++ 2010 residistributable package already installedmemberMember 865677420 Jun '12 - 8:39 
True. I've run into that issue as well. But there's one more, regarding detection on on x64/ia64 (regardless which runtime is installed). I'm adressing that in a separate post "Detecting/Installing VC++ 2010 Runtime".
QuestionDetecting/Installing VC++ 2008 RuntimememberMember 865677418 Feb '12 - 7:04 
I've added a new product script called vcredist2008.iss - what is yet missing is proper detection by registry key, though. This is different to VC++ 2010 (numerous keys and versions possible as far as I can see). I tried to workaround this by using the '/q' switch so that no "repair" dialog occurs if already installed. Still, improvements would be welcome:
 
// requires Windows 7, Windows 7 Service Pack 1, Windows Server 2003 Service Pack 2, Windows Server 2008, Windows Server 2008 R2, Windows Server 2008 R2 SP1, Windows Vista Service Pack 1, Windows XP Service Pack 3
// requires Windows Installer 3.1 or later
// requires Internet Explorer 5.01 or later
// http://www.microsoft.com/downloads/en/details.aspx?FamilyID=9cfb2d51-5ff4-4491-b0e5-b386f32c0992
 
[CustomMessages]
vcredist2008_title=Visual C++ 2008 Redistributable
 
en.vcredist2008_size=3.9 MB
de.vcredist2008_size=3,9 MB
 
en.vcredist2008_size_x64=4.7 MB
de.vcredist2008_size_x64=4,7 MB
 
en.vcredist2008_size_ia64=4.0 MB
de.vcredist2008_size_ia64=4,0 MB
 
;http://www.microsoft.com/globaldev/reference/lcid-all.mspx
en.vcredist2008_lcid=''
de.vcredist2008_lcid='/lcid 1031 '
 

[Code]
const
vcredist2008_url = 'http://download.microsoft.com/download/0/a/5/0a5ce308-1e15-4806-964c-72dbf88de86d/vcredist_x86.exe';
vcredist2008_url_x64 = 'http://download.microsoft.com/download/4/a/9/4a932a53-ab98-44d9-af39-75491eb20006/vcredist_x64.exe';
vcredist2008_url_ia64 = 'http://download.microsoft.com/download/c/9/4/c9494e23-6717-47c3-a061-3cc2ce5453f8/vcredist_IA64.exe';
 
procedure vcredist2008();
var
version: cardinal;
begin
//RegQueryDWordValue(HKLM, 'SOFTWARE\Microsoft\VisualStudio\10.0\VC\VCRedist\' + GetString('x86', 'x64', 'ia64'), 'Install', version);
 
//if (version <> 1) then
AddProduct('vcredist2008' + GetArchitectureString() + '.exe',
CustomMessage('vcredist2008_lcid') + '/q /passive /norestart',
CustomMessage('vcredist2008_title'),
CustomMessage('vcredist2008_size' + GetArchitectureString()),
GetString(vcredist2008_url, vcredist2008_url_x64, vcredist2008_url_ia64),
false, false);
end;

AnswerRe: Detecting/Installing VC++ 2008 RuntimememberMember 865677419 Feb '12 - 23:00 
for now I've changed the procedure as follows:
 
procedure vcredist2008();
var
version: cardinal;
MS, LS: Cardinal;
begin
//RegQueryDWordValue(HKLM, 'SOFTWARE\Microsoft\VisualStudio\10.0\VC\VCRedist\' + GetString('x86', 'x64', 'ia64'), 'Install', version);
//if (version <> 1) then
if GetVersionNumbers(ExpandConstant('{sys}\msvcr90.dll'), MS, LS) = false and GetVersionNumbers('msvcr90.dll', MS, LS) = false then
AddProduct('vcredist2008' + GetArchitectureString() + '.exe',
CustomMessage('vcredist2008_lcid') + '/q /passive /norestart',
CustomMessage('vcredist2008_title'),
CustomMessage('vcredist2008_size' + GetArchitectureString()),
GetString(vcredist2008_url, vcredist2008_url_x64, vcredist2008_url_ia64),
false, false);
end;

GeneralRe: Detecting/Installing VC++ 2008 Runtimememberstfx11 Apr '12 - 11:58 
This might be a bit advanced but you could use the MsiQueryProductState API. See http://blogs.msdn.com/b/astebner/archive/2009/01/29/9384143.aspx[^].
 
Basically you need to define the function like so in Inno Setup: http://stackoverflow.com/questions/7683990/innosetup-msiqueryproductstate[^]
 
Then call it with the appropriate product code which can be seen in the first link Wink | ;)
GeneralRe: Detecting/Installing VC++ 2008 RuntimememberMember 865677420 Jun '12 - 8:37 
Hm, actually I wanted to avoid using product codes, as they potentially change between CPU architetures and service packages - but for my installer it doesn't matter.
 
I've "fixed" that now by migrating to VC++ 10 (2010) - but ran into another issue.
 
Will do a separate post with topic "Detecting/Installing VC++ 2010 Runtime".

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web04 | 2.6.130523.1 | Last Updated 23 Sep 2011
Article Copyright 2007 by stfx
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid