• Innosetup打包自动下载.net framework 动态库及替换卸载程序图标.


    1. 背景
           在使用了一段时间微软自带的安装包打包工具后,总感觉不太顺利,于是便想着找一种更简单稳定的打包工具,这类工具其实还不少,最终经过各种考量,我们选择了 InnoSetup ,该工具是一个完全免费的Windows打包工具,涉及的功能比较全面,并且采用脚本式编辑,完美支持 Pascal 语言.本文简单描述一下如何自动下载安装 .net framework 框架 及更新卸图标的小技巧,当然本文部分内容借鉴了网上一部分的解决方案.在此整理一下已备忘同时分享给有类似需求的朋友.
    2. 放几张安装过程中自动下载文件的截图方便大家参考.
      QQ截图20150710173408QQ截图20150710174115QQ截图20150710174129

    3. 替换卸载程序图标
                   该工具制作的安装包,默认生成的卸载程序使用的是和安装程序一样的图标,这样感觉不够直观,可通过 "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, 0);
      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;
    4. 自动下载.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
      //    'v4Client'     .NET Framework 4.0 Client Profile
      //    'v4Full'       .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 := 'v4Full';
              check45 := true;
          end else
              check45 := false;
      
          // installation key group for all .NET versions
          key := 'SOFTWAREMicrosoftNET Framework SetupNDP' + version;
         
          // .NET 3.0 uses value InstallSuccess in subkey Setup
          if Pos('v3.0', version) = 1 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) = 1 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 >= 378389);
          end;
      
          result := success and (install = 1) 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) = 0 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 = 0) 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',0) 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('v4Full',0) then begin
              isInclued := true;
          end else if version = 'v4Full' 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('v4Client',0) then begin
              isInclued := true;     
          end else if version = 'v4Client' 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',0) then begin
              isInclued := true;     
          end else if Pos('v3.5',version) = 1 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',0) then begin
              isInclued := true;     
          end else if Pos('v3.0',version) = 1 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',0) then begin
              isInclued := true;     
          end else if Pos('v2',version) = 1 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',0) then begin
              isInclued:= true;
          end else if Pos('v1',version)=1 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 := 'v4Full';   
          if not IsIncludeFramework(dotNetVersion) then begin
            if not DoInstallDotNet() then begin
               MsgBox('当前操作需要安装.NET Framework ' + dotNetVersion + '或以上版本。'#13#13
                '在尝试自动安装期间,似乎出现一些小问题(或用户取消了安装),'#13
                '请重试尝试安装。', mbInformation, MB_OK);
              result:= false;
            end;
          end;
        end;   
      end;
    5. 关于通用
            可以将以上两个小功能点分别保存为独立的innosetup 脚本文件(“.iss”),然后在主安装包脚本中引入这两个文件.如下所示.
      #include "dotnetSetup.iss"
      #include "updateuninstallIco.iss"
    6. 后记
      a).“Update.dll” 及 “isxdl.dll”如果你实在是找不到,本文提供一个下载链接,可从这里下载.
      b).  本文中部分方法及思路收集于网络,本人只是加以整理用以备忘.
  • 相关阅读:
    BZOJ3670:[NOI2014]动物园(KMP)
    415. [HAOI2009] 旅行
    U10223 Cx大帝远征埃及
    U10206 Cx的治疗
    2741. [济南集训 2017] 掰巧克力
    复习题目汇总 over
    7-20 表达式转换(25 分)
    7-19 求链式线性表的倒数第K项(20 分)(单链表定义与尾插法)
    7-18 银行业务队列简单模拟(25 分)
    7-17 汉诺塔的非递归实现(25 分)(有待改进)
  • 原文地址:https://www.cnblogs.com/xie-zhonglai/p/innosetup_auto_setup_framework_and_update_ico.html
Copyright © 2020-2023  润新知