Installing .NET Framework 2.0 Applications with InstallShield
原帖地址http://www.codeproject.com/KB/install/installdotnet2.aspx
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:
- Detecting whether the target platform has .NET v2.0 already installed.
- Checking that the target platform has the necessary software to support .NET v2.0.
- Installing the support software required by .NET 2.0 � as needed.
- Installing .NET 2.0 � as needed.
- 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:
- 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.
- 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:
- Open the InstallShield IDE and create a new project in the usual way.
- Switch to the Installation Designer View and open the Behaviour and Logic folder.
- 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.
- 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.
- 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.
- 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'.
- 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
- DetectDotNet was adapted from "The coding gentleman's guide to detecting the .NET Framework (v2.2)" by Nishant Sivakumar.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现