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

Installing .NET Framework 2.0 Applications with InstallShield

By , 13 Nov 2005
 

Introduction

This article describes my attempts at deploying a .NET Framework 2.0 application using InstallShield X. I'm not really happy with the outcome, but hopefully it will help someone understand the issues and perhaps pave the way for something better.

InstallShield X provides a helpful deployment wizard that allows you to select the version of .NET Framework from a drop-down list box. This takes out of your hands all the messy business of detecting the .NET version on the target platform and installing the appropriate framework; you just make your selection and it's all done for you. Unfortunately, the list box doesn't support .NET v2.0 and after consulting the Macrovision website it became clear that there are no plans to address this issue in the near future; see this. It was for this reason that I decided to write this article.

The problem can be split into the following steps:

  1. Detecting whether the target platform has .NET v2.0 already installed.
  2. Checking that the target platform has the necessary software to support .NET v2.0.
  3. Installing the support software required by .NET 2.0 – as needed.
  4. Installing .NET 2.0 – as needed.
  5. Installing my application.

I found a program called DetectDotNet after searching CodeProject. This seemed to do most of what was required for the first step. However, it needed a bit of surgery before it could take the required .NET Framework as an input parameter and return a suitable exit code; see Listing 1. My plan was to create an InstallShield script and custom action that would launch DetectDotNet and run the necessary installation packages before continuing with the installation; see Listing 2. However, I ran into the following problems, which is why I'm not too happy with the overall result:

  1. InstallShield script doesn't recognize MS-DOS exit values so you have to run DetectDotNet from a batch file, test the %errorlevel% and then create a file for the InstallShield script to detect; see Listing 3.
  2. The .NET 2.0 Framework requires Windows Installer 3.0 (for NT), but unfortunately it doesn't seem that you can't install it from inside another installation program. I couldn't think of a way around this problem apart from writing a kind of bootstrap installer program. Ideas anyone?

The solution presented here doesn't check whether Windows Installer 3.0 has been installed on the target platform because I ran out of time. The best I can suggest for now is that you tell the user to install Windows Installer 3.0 before running your setup.exe (or App.msi). Installing this program multiple times doesn't seem to hurt.

The dependency on Windows Installer 3.0 (or 3.1) seems to imply that the only supported environments for .NET v2.0 are:

  • Windows 2000 sp3 and sp4
  • Windows Server 2003
  • Windows XP sp2

However, you can use Windows Installer 2.0 for non-NT platforms so this extends your reach to:

  • Windows 98
  • Windows 98 SE
  • Windows ME

[Thanks to David Kean for informing me about the above dependencies]. You can find the redistributables for Windows Installer 3.1 (WindowsInstaller-KB893803-v2-x86.exe) and .NET v2.0 Framework (dotnetfx.exe) in the Microsoft website.

I created the installation program and the script using InstallShield X, but other versions work in a similar fashion:

  1. Open the InstallShield IDE and create a new project in the usual way.
  2. Switch to the Installation Designer View and open the Behaviour and Logic folder.
  3. Click on 'Support Files' in the left view and right-click | Insert Files in the right view to add the files: detect.cmd, DetectDotNet.exe and dotnetfx.exe.
  4. Click on 'InstallScript' in the left view, select the 'Files' folder in the middle view and then right-click | New Script File. This opens a script template in the right view into which you should type Listing 2 as your custom function.
  5. Click on 'Custom Actions' in the left view, select the 'Custom Actions' item in the middle view and then right-click | Custom Action Wizard. Give your action a suitable name, select its type as 'Run InstallScript Code', select the name of your custom function as Source; see step 4, and use defaults for the remaining.
  6. Click on 'Sequences' in the left view and select the 'User Interface' item in the 'Installation' folder in the middle view. Right-click | Insert opens the Insert Action dialog where you will find your 'Custom Action' created in step 5. Select this item and press OK. Move your custom action until it is just after 'ISSetupFilesExact'.
  7. Run the Release Wizard (Build | Release Wizard) to create your installation.

Listing 1: MainDetectDotNet.cpp

//*******************************************
//program takes an optional single parameter, 
//the version of CLR to find. The
//program returns 0 (success)if this version 
//of CLR is found, otherwise it
//returns -1 (fail). If no parameter is given 
//the program returns 0 (success).
//
// examples:
//  c:\>DetectDotNet 1.2.4455 //returns 0 if v 1.2.4455 is found
//  c:\>DetectDotNet 2.0*     //returns 0 if any v2.0 of CLR is found
//  c:\>DetectDotNet 1.*      //returns 0 if any v 1. of CLR is found
//  c:\>DetectDotNet *        //returns 0 if any version of CLR is found
//  c:\>DetectDotNet          //returns 0 whether CLR is found or not
//**********************************************************************
int _tmain(int argc, _TCHAR* args[])        
{
    int rc = 0;                
    size_t matchLen = 0;        
    CDetectDotNet detect;

    if ( argc > 1 )    
    {
        matchLen = _tcslen(args[1]);
        for ( size_t x = 0; x < matchLen; x++ )
        {
            if ( args[1][x] == '*' )
            {
                matchLen = x;
                args[1][x] = '\0';
            }
        }
        cout << "searching for v" << args[1] << endl;
        rc = -1;                                
    }

    vector<STRING> CLRVersions;

       // cout lines ommitted for clarity

    for(vector<STRING>::iterator it = CLRVersions.begin(); 
        it < CLRVersions.end(); it++)
    {
        cout << *it << endl;
        if ( rc == -1)                        
        {
            if ((*it).compare(0,matchLen,args[1]) == 0)
            {
                cout << "matching CLR found" << endl;
                rc = 0;
            }
        }
    }
        return rc;                            
}

Listing 2: InstallShield script

#define CHECKPROGRAM   SUPPORTDIR^"Detect.cmd"
#define BOOTPROGRAM   SUPPORTDIR^"dotnetfx.exe"
        
#include "ifx.h"

export prototype DetectDotNet2(HWND);  

/////////////////////////////////////////////////////////////////////
//                                                                           
// Function:  MyFunction
//                                                                           
//  Purpose:  This function will be called by the script engine when 
//            Windows(TM) Installer executes your custom action 
//            (see the "To Do," above).
//                                                                           
/////////////////////////////////////////////////////////////////////
function DetectDotNet2(hMSI)  
    STRING svResult;
    BOOL bExit, bLaunchAndWait;
begin 
            
 LaunchAppAndWait (CHECKPROGRAM, "", LAAW_OPTION_WAIT |
                                     LAAW_OPTION_HIDDEN);
           
  if (FindFile (SUPPORTDIR, "Found.txt", svResult) < 0) then

     AskOptions (EXCLUSIVE, ".NET Framework 2.0 Deployment",
                 "Install .NET Framework 2.0", bLaunchAndWait,
                 "Abort installation", bExit);

     if bExit  then
         abort;
     endif;
               
     if (LaunchAppAndWait(BOOTPROGRAM, "", LAAW_OPTION_WAIT) < 0) then       
         abort;
     endif;
  endif;
end;

Listing 3: Simple batch file

echo off
detectdotnet 2.*
if %errorlevel% EQU 0 (echo found > found.txt)

Acknowledgement

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Will Stott
Web Developer
United Kingdom United Kingdom
Member
A software developer

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   
QuestionGenerate single msi or exe file using InstallShield Developer 8memberPhyoe11 Mar '12 - 22:22 
Hi All,
 
Is it possible to make single setup.msi or setup.exe file for .Net framework 2.0 and 4.0 by using Installshield Developer 8 Version.
 
When I tried to generate with it, I always get setup.msi and setup.exe. I cannot create as a single file.
Phyoe Khaing Min

GeneralAlternative waymemberMPullmann22 Oct '07 - 0:07 
I managed to install the .NET Framework 2.0 in an InstallShield 11 Setup by creating my own Setup Prerequisite, using the Prerequisite Editor. You can check for existence of the registry key HKEY_LOCAL_MACHINE\Software\Microsoft\Net Framework Setup\NDP\v2.0.50727 as the condition.
QuestionAnother method?memberjnewmoyer6 Apr '07 - 8:11 
This way may not be as fullproof as the one above but its working for me. Registry key is discussing the the Microsoft article http://support.microsoft.com/kb/315291
 

function InstallDotNet(hMSI)
string dotnetInstaller, szKey;
begin
dotnetInstaller = "\\dotnetfx.exe";
RegDBSetDefaultRoot(HKEY_LOCAL_MACHINE);
szKey = "SOFTWARE\\Microsoft\\.NETFramework\\Policy\\v2.0";
if (RegDBKeyExist(szKey) < 0) then
MessageBox (".NET Framework 2.0 Registry key not found", INFORMATION);
LaunchAppAndWait(SRCDIR + dotnetInstaller, "", LAAW_OPTION_WAIT);
else
MessageBox(".NET Framework 2.0 Found", INFORMATION);
endif;
end;
GeneralHowto install .net 2.0 with IS using a custom actionmemberbrianthenewbee3 Apr '07 - 10:57 
This is one way to install .net 2.0 in IS 10.5 (maybee earlier versions)...
Add a new custom action to run an embedded exe.
The dotnetfx.exe for .net 2 can be added to the binary table of the msi. Then, to get a silent install, in the command line parameters to pass into dotnetfx.exe enter:
/q:a /c:"install.exe /q"
 
To conditionally install if .net 2 is already installed, add to the custom action condition:
MsiNetAssemblySupport < "2.0.50727.42"

GeneralRe: Howto install .net 2.0 with IS using a custom action [modified]memberisurusk5 Apr '07 - 22:39 
Could u please give some detail about “MsiNetAssemblySupport < "2.0.50727.42"" i cant find a place to put the condition
 

-- modified at 5:30 Friday 6th April, 2007
NewsRe: Howto install .net 2.0 with IS using a custom actionmemberStickyC13 Jun '07 - 7:13 
Note that this will fail under Vista as the MSINetAssemblySupport value for Vista is 2.0.50727.312 and InstallShield evaluates the test as a string, so it thinks that .312 is actually less than .42.

General2.0 Unattended with Progress/StatusmemberDarkSolace22 Jan '07 - 23:51 
First off...GREAT post here...this is a real issue for those of us using InstallShield (Editor) X (10.0).
 
Here is my little addition to your thoughts. I also needed to build an installer which installed the .NET Framework 2.0 automatically based on if it was already installed or not...BUT I really felt that doing a simple quiet (/q) dotnetfx.exe install left the user hanging too long without any status, information or even any idea if the installer was still running or not. I am sure that there is an easier way to accomplish this but here is how I did it using a combination of your approach and some other information I dug up.
 
First, there isn't any way to do a "/passive" .NET Framework 2.0 Installation (at least that I could figure out) and after much digging I found a pre-compiled Framework Installer which is self extracting, unattended installing and generates progress/status windows so the end user knows what is going on. Here is the download link for that:
 
http://download.ryanvm.net/files/dotnet2.exe[^]
 
Then, in the Installshield Project, I just used your .NET CLR checker to verify if .NET 2.0 was installed and if it's not had the installer kick off the unattended 2.0 setup and wait for completion. It seems to be working great.
 

#define CHECKPROGRAM SUPPORTDIR^"Detect.cmd"
#define BOOTPROGRAM SUPPORTDIR^"dotnet2.exe"

#include "ifx.h"
 
export prototype DetectDotNet2(HWND);
 
/////////////////////////////////////////////////////////////////////
//
// Function: MyFunction
//
// Purpose: This function will be called by the script engine when
// Windows(TM) Installer executes your custom action
// (see the "To Do," above).
//
/////////////////////////////////////////////////////////////////////
function DetectDotNet2(hMSI)
STRING svResult;
begin

LaunchAppAndWait (CHECKPROGRAM, "", LAAW_OPTION_WAIT |
LAAW_OPTION_HIDDEN);

if (FindFile (SUPPORTDIR, "Found.txt", svResult) < 0) then
if (LaunchAppAndWait(BOOTPROGRAM, "", WAIT) < 0) then
MessageBox ("Error installing .NET Framework 2.0", WARNING);
endif;
endif;
end;

 
Like I said I am sure there is an easier/cleaner way to accomplish this...but it seems to be working for me. Thanks again and if anyone has any input please let me know.

GeneralCAUTION!!! Re: 2.0 Unattended with Progress/StatusmemberDarkSolace24 Jan '07 - 12:49 
Hey all,
Just a quick cautionary update to my last post and I am not 100% sure this isn’t some “one-off” issue…but better safe than sorry:
 
DON’T INSTALL THAT pre-compiled Framework Installer from http://download.ryanvm.net/files/dotnet2.exe on any computers which have Visual Studio .NET 2005 Installed on them. I cant be 100% sure but it seems that installing the .NET Framework 2.0 Updates that are included with this cause some issues with VS .NET 2005 opening .sln (Solution) files.
 
After I did so I got an error when opening ALL my 2005 Solutions stating “Unable to Load ”.
 
FIX:
 
To resolve this issue I simply uninstalled the .NET Framework 2.0 Updates which this installer applied (Add/Remove Programs…Click the “Show Updates” checkbox…locate Microsoft .NET Framework 2.0…the updates are listed as sub-items). This fixed the problem.
 
The Framework installer from http://download.ryanvm.net/files/dotnet2.exe works great on any system which doesn’t have VS.NET 2005 on so I am still ok with using it as a deployment solution to my end users…but I just wanted to make everyone aware of this potential issue I uncovered AFTER posted my last thoughts. Thanks!

GeneralDetect .NET 2.0 and Silent install from scriptmemberJim McFarlane14 Apr '06 - 4:27 
I needed to detect .NET 2.0 installation, then install silently from an InstallShield X script.
 
http://support.microsoft.com/default.aspx?scid=kb;en-us;Q318434
 
At this link, Microsoft support has an article describing silent install (SMS: How to Use SMS 2.0 to Silently Install .NET Framework).
 
      svDotNetDir = WINDIR ^ "Microsoft.NET\\Framework\\v2.0.50727";
      // if RegAsm is already in the .NET 2.0 folder, the Framework is installed
      // if Framework not installed, install it!
      if (FindFile (svDotNetDir, "RegAsm.exe", svResult) < 0) then
         // Install .NET Framework 2.0
         ChangeDirectory (TARGETDIR);
         szCommandLine = TARGETDIR ^ "dotnetfx.exe";
         LongPathToQuote (szCommandLine, TRUE);
         if (LaunchAppAndWait(szCommandLine, " /q:a /c:\"install /q\" ", WAIT) < 0) then
                     szMsg = "Error installing .NET Framework 2.0";
            MessageBox (szMsg, WARNING);
         endif;           
   endif;

 
Jim McFarlane
GeneralInteresting ApproachmemberTim McCurdy13 Feb '06 - 10:55 
This is an interesting approach. I have always HATED the way InstallShield "hardcoded" which .NET Frameworks could be installed. Once I realized that their "DotNetFx.exe" is a custom application which downloads / installs the DotNet framework...I stopped using it. Why do I want more overhead in a setup Mad | :mad: ! What I could never figure out is why InstallShield couldn't make the different versions of the Framework a simple Xml file or INI setting (probably so they can charge for upgrades everytime a new version of the Framework is released).
 
Anyway, I had developed a custom Script file for installing .NET applications which was all done entirely in InstallScript. It checked the registry for the version and service pack level of the Framework. Whenever a new version or service pack for .NET would come out, I would simply extract all the files from the Dotnetfx.exe (distributed by MS not IS) and viola! It's been working great for years!

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

Permalink | Advertise | Privacy | Mobile
Web03 | 2.6.130523.1 | Last Updated 13 Nov 2005
Article Copyright 2005 by Will Stott
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid