- 在使用了一段时间微软自带的安装包打包工具后,总感觉不太顺利,于是便想着找一种更简单稳定的打包工具,这类工具其实还不少,最终经过各种考量,我们选择了 InnoSetup ,
该工具是一个完全免费的Windows打包工具,涉及的功能比较全面,并且采用脚本式编辑,完美支持 Pascal 语言.本文简单描述一下如何自动下载安装 .net framework 框架 及更新卸图标的小技巧,当然本文部分内容借鉴了网上一部分的解决方案.在此整理一下已备忘同时分享给有类似需求的朋友.
- 替换卸载程序图标
该工具制作的安装包,默认生成的卸载程序使用的是和安装程序一样的图标,这样感觉不够直观,可通过 "UpdateIcon.dll" 插件完成. 如下脚本所示.[Files]
Source: "UpdateIcon.dll"; Flags: dontcopy
Source: "uninstall.ico"; Flags: dontcopy [Icons]
Name: "{group}\卸载"; Filename: "{uninstallexe}" [Code]
function UpdateIcon(const hWnd: Integer; const exeFileName, exeIcon, IcoFileName: String; wlangID: DWORD): Boolean;
external 'UpdateIcon@files:UpdateIcon.dll stdcall'; //替换卸载图标
function UpdateUninstIcon(const IcoFileName: String): Boolean;
begin
Result:= UpdateIcon(MainForm.Handle, '', '', IcoFileName, );
end; //安装步骤进行开始替换卸载图标
procedure CurStepChanged(CurStep: TSetupStep);
var
sIcon: String;
begin
if CurStep=ssInstall then
begin
sIcon:= ExpandConstant('{tmp}\uninstall.ico'); //定义卸载图标
ExtractTemporaryFile(ExtractFileName(sIcon)); //释放卸载图标
UpdateUninstIcon(sIcon);//替换卸载图标
end;
end; - 自动下载.net framework 组件并安装
可通过 “isxdl.dll” 扩展实现,动态从网络上添加一个待下载的文件,并在下载完之后自动运行.见如下示例. -
[Code]
var
dotNetDownloadNeeded: boolean;
dotNetLocalPath:string; procedure isxdl_AddFile(URL, Filename: PAnsiChar);
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: PAnsiChar): Integer;
external 'isxdl_SetOption@files:isxdl.dll stdcall'; //检测是否存在特定版本的.net framework
function IsDotNetDetected(version: string; service:cardinal): boolean;
// Indicates whether the specified version and service pack of the .NET Framework is installed.
//
// version -- Specify one of these strings for the required .NET Framework version:
// 'v1.1.4322' .NET Framework 1.1
// 'v2.0.50727' .NET Framework 2.0
// 'v3.0' .NET Framework 3.0
// 'v3.5' .NET Framework 3.5
// 'v4\Client' .NET Framework 4.0 Client Profile
// 'v4\Full' .NET Framework 4.0 Full Installation
// 'v4.5' .NET Framework 4.5
//
// service -- Specify any non-negative integer for the required service pack level:
// 0 No service packs required
// 1, 2, etc. Service pack 1, 2, etc. required
var
key: string;
install, release, serviceCount: cardinal;
check45, success: boolean;
begin
// .NET 4.5 installs as update to .NET 4.0 Full
if version = 'v4.5' then begin
version := 'v4\Full';
check45 := true;
end else
check45 := false; // installation key group for all .NET versions
key := 'SOFTWARE\Microsoft\NET Framework Setup\NDP\' + version; // .NET 3.0 uses value InstallSuccess in subkey Setup
if Pos('v3.0', version) = then begin
success := RegQueryDWordValue(HKLM, key + '\Setup', 'InstallSuccess', install);
end else begin
success := RegQueryDWordValue(HKLM, key, 'Install', install);
end; // .NET 4.0/4.5 uses value Servicing instead of SP
if Pos('v4', version) = then begin
success := success and RegQueryDWordValue(HKLM, key, 'Servicing', serviceCount);
end else begin
success := success and RegQueryDWordValue(HKLM, key, 'SP', serviceCount);
end; // .NET 4.5 uses additional value Release
if check45 then begin
success := success and RegQueryDWordValue(HKLM, key, 'Release', release);
success := success and (release >= );
end; result := success and (install = ) and (serviceCount >= service);
end; //准备安装.net framework需要的条件(本地还是联网)
function PreInstallDotNet(dotNetName:string;dotNetDownloadUrl:string):boolean;
begin
if (not IsAdminLoggedOn()) then begin
MsgBox('您电脑安装 Microsoft .NET Framework 需要管理员权限', mbInformation, MB_OK);
Result := false;
end else begin
dotNetLocalPath := ExpandConstant('{src}') + '\'+dotNetName;
if not FileExists(dotNetLocalPath) then begin
dotNetLocalPath := ExpandConstant('{tmp}') + '\'+dotNetName;
if not FileExists(dotNetLocalPath) then begin
isxdl_AddFile(dotNetDownloadUrl, dotNetLocalPath);
dotNetDownloadNeeded := true;
end;
end; SetIniString('install', 'dotnetRedist', dotNetLocalPath, ExpandConstant('{tmp}\dep.ini'));
end; end; //执行安装.net framework
function DoInstallDotNet():boolean;
var
hWnd: Integer;
ResultCode: Integer;
begin
result := true;
hWnd := StrToInt(ExpandConstant('{wizardhwnd}')); // don’t try to init isxdl if it’s not needed because it will error on < ie 3
if dotNetDownloadNeeded then begin
isxdl_SetOption('label', '正在下载 Microsoft .NET Framework');
isxdl_SetOption('des-c-r-i-p-tion', '您还未安装Microsoft .NET Framework. 请您耐心等待几分钟,下载完成后会安装到您的的计算机中。');
if isxdl_DownloadFiles(hWnd) = then result := false;
end; if result = true then begin
if Exec(ExpandConstant(dotNetLocalPath), '/qb', '', SW_SHOW, ewWaitUntilTerminated, ResultCode) then begin
// handle success if necessary; ResultCode contains the exit code
if not (ResultCode = ) then begin
result := false;
end;
end else begin
// handle failure if necessary; ResultCode contains the error code
result := false;
end;
end; end; //检测是否安装了等于大于指定版本的.net framework
function IsIncludeFramework(version: string): boolean;
var
isInclued:boolean;
begin //最高版本的
if IsDotNetDetected('v4.5',) then begin
isInclued := true;
end else if version = 'v4.5' then begin
PreInstallDotNet('dotNetFx45_Full_setup.exe','http://download.microsoft.com/download/B/A/4/BA4A7E71-2906-4B2D-A0E1-80CF16844F5F/dotNetFx45_Full_setup.exe');
end else if IsDotNetDetected('v4\Full',) then begin
isInclued := true;
end else if version = 'v4\Full' then begin
PreInstallDotNet('dotNetFx40_Full_x86_x64.exe','http://download.microsoft.com/download/9/5/A/95A9616B-7A37-4AF6-BC36-D6EA96C8DAAE/dotNetFx40_Full_x86_x64.exe');
end else if IsDotNetDetected('v4\Client',) then begin
isInclued := true;
end else if version = 'v4\Client' then begin
PreInstallDotNet('dotNetFx40_Client_x86_x64.exe','http://download.microsoft.com/download/5/6/2/562A10F9-C9F4-4313-A044-9C94E0A8FAC8/dotNetFx40_Client_x86_x64.exe');
end else if IsDotNetDetected('v3.5',) then begin
isInclued := true;
end else if Pos('v3.5',version) = then begin
PreInstallDotNet('dotNetFx35setup.exe','http://download.microsoft.com/download/7/0/3/703455ee-a747-4cc8-bd3e-98a615c3aedb/dotNetFx35setup.exe');
end else if IsDotNetDetected('v3.0',) then begin
isInclued := true;
end else if Pos('v3.0',version) = then begin
PreInstallDotNet('dotNetFx35setup.exe','http://download.microsoft.com/download/7/0/3/703455ee-a747-4cc8-bd3e-98a615c3aedb/dotNetFx35setup.exe');
end else if IsDotNetDetected('v2.0.50727',) then begin
isInclued := true;
end else if Pos('v2',version) = then begin
PreInstallDotNet('dotnetfx.exe','http://download.microsoft.com/download/5/6/7/567758a3-759e-473e-bf8f-52154438565a/dotnetfx.exe');
end else if IsDotNetDetected('v1.1.4322',) then begin
isInclued:= true;
end else if Pos('v1',version)= then begin
PreInstallDotNet('dotNetFx35setup.exe','http://download.microsoft.com/download/7/0/3/703455ee-a747-4cc8-bd3e-98a615c3aedb/dotNetFx35setup.exe');
end; result := isInclued;
end; //点击下一步
function NextButtonClick(CurPage: Integer): Boolean;
var
dotNetVersion:String;
begin
Result := true;
if (CurPage = wpReady) then begin
dotNetVersion := 'v4\Full';
if not IsIncludeFramework(dotNetVersion) then begin
if not DoInstallDotNet() then begin
MsgBox('当前操作需要安装.NET Framework ' + dotNetVersion + '或以上版本。'##
'在尝试自动安装期间,似乎出现一些小问题(或用户取消了安装),'#
'请重试尝试安装。', mbInformation, MB_OK);
result:= false;
end;
end;
end;
end;关于通用
可以将以上两个小功能点分别保存为独立的innosetup 脚本文件(“.iss”),然后在主安装包脚本中引入这两个文件.如下所示. #include "dotnetSetup.iss"
#include "updateuninstallIco.iss"