跟我学习InstallShield(2)

跟我制作安装包 ----byRuralMouse
第二个实例 功能强大的脚本

新增的约束与功能

第一个安装包完成后我找到了经理,下面是我们的对话:

我: 经理,安装包完成了,我对InstallShield环境和制作安装包有了初步的理解。不过我感觉这个安装包太土了, 这些功能通过Dos命令完全可以实现,这么做有必要吗?

经理:呵呵,的确制作一个如此简单的安装包就是用InstallShield,的确有点杀鸡用牛刀的感觉,不过,这只是最基本的 要求,目的是让你熟悉InstallShield环境,完成整个比对引擎的安装包还要做很多工作。

我:哦?我说呢,还要加入什么约束。

经理:首先,②要运行我们的比对引擎要求目标机器有VC2008 SP1的运行环境,当前的安装包里面没有。

我:明白,那我在安装包中检测一下用户机器上是不是安装了这个软件,如果没有安装我就让用户安装一下。

经理:给,这个vcredist_x86_2008_sp1.exe是VC2008 SP1的运行环境安装包,你把他集成在现有的安装包里面。

(拷贝文件)

经理:其次,③用户要运行我们的系统,需要两个授权文件THIDFaceLicense.dat和THIDQualityLicense.dat,由于不同的 机器上这两个文件都不同,所以无法把这两个文件放到现有的安装包里面。但是,如果用户机器上有这两个授权文件,应该在安装时 帮用户将授权文件拷贝到安装路径下。

我:好的。如果用户没有这两个授权文件,我可不可以禁止它安装。

经理:可以。④这次的安装包还要求卸载时可以实现完整的卸载,由于VC2008运行环境的安装和授权文件的拷贝, 可能在卸载时卸载不干净,这样很不友好。

我:好的。

经理:对了,⑤我们的程序最好部署在系统盘以外的磁盘(如果有的话),但是允许用户安装在系统盘,这时要给出一个提示。

经理:还有,①这次的安装包要专业一点,加上一个软件使用许可协议界面

我:恩,我记下了。

(经理欲言又止)

我:还有什么要求吗?

经理:呃,有,这个例子就以脚本为主吧,剩下的功能在下一个例子里面定制。

我:收到,那我开动了。

安装前的设计与准备

        为了与上一次的工作区分开来,我复制了一个Example1文件夹到相同的路径下并改名为Example2,在Example2文件夹下面建立了一个Support 文件夹并把vcredist_x86_2008_sp1.exe和从产品部要来的《软件许可协议.txt》放到了里面。为了完成这个安装包,我做了一些工作, 研究了一下InstallShield脚本语法。参考大家的脚本之后,我明白了制作一个好的安装包, 脚本可以起到很重要的作用,脚本编写需要注意两点:1、用什么函数,2、在什么地方写脚本。这是因为完成同一功能的脚本有很多, 脚本的灵活性也使得我们很容易制作出变异的安装包。我的经验是多研究别人的脚本和正规软件的安装包。充电完毕, 我双击Example2文件夹下面的FARSMatchEngine.ism 启动了InstallShield。

第一个任务 增加许可协议界面

        呵呵,之所以把它排在了第一个,是因为它最简单。这次我们工作的环境主要是Installation designer了。在左侧窗口中找到Behavior and Logic,定位到其子项Support Files/Billboards,单击该项,在中间的Support Files/language Independent 下添加我们的许可文件 《软件许可协议.txt》,参照大多数安装包,软件许可协议出现在欢迎界面之后。因此,我们通过向导增加函数(Before Move Data) OnFirstUIBefore,向导生成的脚本如下:

 //---------------------------------------------------------------------------
 // OnFirstUIBefore
 //
 // The OnFirstUIBefore event is called by the framework when the setup is
 // running in first install mode. By default this event displays UI allowing
 // the end user to specify installation parameters.
 //---------------------------------------------------------------------------
 function OnFirstUIBefore()
      NUMBER nResult, nSetupType, nvSize, nUser;
      STRING szTitle, szMsg, szQuestion, svName, svCompany, szFile;
      STRING szLicenseFile;
      BOOL bCustom, bIgnore1, bIgnore2;
 begin  
      // TO DO: if you want to enable background, window title, and caption bar title
      // SetTitle( @PRODUCT_NAME, 24, WHITE );
      // SetTitle( @PRODUCT_NAME, 0, BACKGROUNDCAPTION );
      // Enable( FULLWINDOWMODE );
      // Enable( BACKGROUND );
      // SetColor(BACKGROUND,RGB (0, 128, 128));

      // Added in InstallShield 15 - Show an appropriate error message if
      // -removeonly is specified and the product is not installed.
      if( REMOVEONLY ) then
          Disable( DIALOGCACHE );
          szMsg = SdLoadString( IDS_IFX_ERROR_PRODUCT_NOT_INSTALLED_UNINST );
          SdSubstituteProductInfo( szMsg );
          MessageBox( szMsg, SEVERE );
          abort;
      endif;

      nSetupType = TYPICAL;

 Dlg_SdWelcome:
      szTitle = "";
      szMsg   = "";
      nResult = SdWelcome(szTitle, szMsg);
      if (nResult = BACK) goto Dlg_SdWelcome;

      szTitle   = "";
      svName    = "";
      svCompany = "";

 Dlg_SdRegisterUser:
      szMsg = "";
      szTitle = "";
      nResult = SdRegisterUser( szTitle, szMsg, svName, svCompany );
      if (nResult = BACK) goto Dlg_SdWelcome;

 Dlg_SetupType:
      szTitle = "";
      szMsg   = "";
      nResult = SetupType2(szTitle, szMsg, "", nSetupType, 0);
      if (nResult = BACK) then
          goto Dlg_SdRegisterUser;
      else
          nSetupType = nResult;
          if (nSetupType != CUSTOM) then
              nvSize = 0;
              FeatureCompareSizeRequired(MEDIA, INSTALLDIR, nvSize);
              if (nvSize != 0) then
                  MessageBox(szSdStr_NotEnoughSpace, WARNING);
                  goto Dlg_SetupType;
              endif;
              bCustom = FALSE;
              goto Dlg_SQL;
          else
              bCustom = TRUE;
          endif;
      endif;

 Dlg_SdAskDestPath:
      nResult = SdAskDestPath(szTitle, szMsg, INSTALLDIR, 0);
      if (nResult = BACK) goto Dlg_SetupType;

 Dlg_SdFeatureTree:
      szTitle    = "";
      szMsg      = "";
      if (nSetupType = CUSTOM) then
          nResult = SdFeatureTree(szTitle, szMsg, INSTALLDIR, "", 2);
          if (nResult = BACK) goto Dlg_SdAskDestPath;
      endif;

 Dlg_SQL:
      nResult = OnSQLLogin( nResult );
      if( nResult = BACK ) then
          if (!bCustom) then
              goto Dlg_SetupType;
          else
              goto Dlg_SdFeatureTree;
          endif;
      endif;

 Dlg_SdStartCopy:
      szTitle = "";
      szMsg   = "";
      nResult = SdStartCopy2( szTitle, szMsg );

      if (nResult = BACK) then
          goto Dlg_SQL;;
      endif;

      // Added in IS 2009 - Set appropriate StatusEx static text.
      SetStatusExStaticText( SdLoadString( IDS_IFX_STATUSEX_STATICTEXT_FIRSTUI ) );

      // setup default status
      Enable(STATUSEX);

      return 0;
 end;

 

在OnFirstUIBefore的参数列表中增加参数声明

 BOOL bAcceptLicense; // 用户是否接受了协议要求(为什么要加这个变量?自己思考吧)

在Dlg_SdRegisterUser:之前添加我们的代码以显示软件协议对话框,代码如下:

 ...
 svCompany = "";
 if(!MAINTENANCE)then
      nResult = SdLicense2   ("软件许可协议 ", "", "", SUPPORTDIR ^ "软件许可协议.txt", FALSE);
      if (nResult = BACK) goto Dlg_SdWelcome;
      bAcceptLicense=TRUE; //用户接受了协议
 endif;
 Dlg_SdRegisterUser:
 ...


修改Dlg_SdRegisterUser:最后的跳转语句为

 if (nResult = BACK) goto Dlg_License;
调试运行我们的脚本,应该可以顺利的出现我们的协议许可对话框,并且向导按钮也合乎逻辑

第二个任务 检测安装辅助软件

        由于现在软件系统的复杂性,我们开发测程序一般不能直接在客户机器上直接运行,在部署我们的软件时我们需要安装一些 必要的辅助环境。在制作安装包的时候我们可以不管用户系统上是否已经安装了运行环境而直接进行运行环境的安装, 这样在编写脚本的时候比较省事,但是这种做法常常很不友好,经常出现运行环境的卸载对话框......。我认为最好的办法是 先检测目标机器上是否已经安装了该运行环境,然后再决定运行环境支持软件的安装。因此,第二个任务可以划分为两个子任务:

检测目标机器上是否已经安装了指定软件

        由于大多数软件采取定制安装的形式部署在客户的计算机上,我们不能通过文件夹定位的方式决定某软件是否安装。现在的磁盘容量 越来越大,使用全盘搜索的方式也很不现实。在Windows系统上大多数软件的安装信息都记录在注册表中,现在大多数运行环境的软件的安装信息 都可以从注册表中获得。通过注册表比较工具可以获得特定软件在安装前后注册表的变化,通过分析该变化可以确定某软件是否安装在目标机器上。 本例中我们要安装的是VC2008 SP1的运行环境,通过注册表比较工具我们可以知道在安装有VC2008 SP1 运行环境的机器的注册表中会包含注册表项:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{9A25302D-30C0-39D9-BD6F-21E6EC160475} 所以,我们可以通过该注册表项的存在与否来判断VC2008 SP1的运行环境是否已经安装。

运行环境软件的安装

        使用脚本运行指定程序的方法有很多种,这里只介绍使用函数LaunchAppAndWait来安装VC运行环境。与显示软件协议一样, VC运行环境安装包放入我们的安装包工程中,方法和位置与前面的类似,这里不再叙述。软件运行环境的安装一般是在验证用户合法性, 用户设置完特定参数后,开始将安装文件拷本到用户机器之前进行,这里我们通过向导添加函数OnInstallFilesActionBefore,然后修改该函数, 修改后的函数如下:

//---------------------------------------------------------------------------
 // OnInstallFilesActionBefore
 //
 // The InstallFilesActionBefore event is called just before the standard MSI
 // action 'InstallFiles' is executed.
 //---------------------------------------------------------------------------
 function OnInstallFilesActionBefore()  
      string szKey;
 begin   
      // 注册表中记录VC2008 SP1运行环境安装信息的注册表值
      szKey = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{9A25302D-30C0-39D9-BD6F-21E6EC160475}";

      RegDBSetDefaultRoot(HKEY_LOCAL_MACHINE);//设置默认注册表基本键,下面的相对路径就是 此目录下         
      //从注册表中获得某一安装软件的目录
      if (RegDBKeyExist(szKey) < 0)  then   // 目标机器上没有安装VC2008 SP1运行环境                
          if(!MAINTENANCE)  then // 安装依赖环境
              if(LaunchAppAndWait (SUPPORTDIR ^"vcredist_x86_2008_sp1.exe","", WAIT) < 0) then
                  MessageBox ("未找到VC2008 SP1运行环境的安装文件,不能继续安装", INFORMATION);
                  abort; // 终止安装过程
              endif; 
          endif;
      endif;
 end;
第三个任务 授权文件的验证与拷贝

        如果用户没有授权文件,我要阻止用户进行安装,并且阻止的越早越好。如果用户输入一大堆信息,进行一系列选择后发现自己不能安装, 脾气不好的用户会#%^#*&(*的。这里对授权文件的验证,仅限于存在与否的验证,更高级的验证功能可以通过调用第三方程序来进行验证。 (这个版本我就偷懒了:-) )。为了简单,我们最好让用户将授权文件拷贝到我们安装包的同一路径下,然后进行安装, 为了在安装包的最开始进行验证,并在安装过程中将该授权拷贝到用户选择的安装路径。为了演示更多的脚本,本示例在发现用户没有授权时 只是提示用户,并允许用户继续安装。我们先定义一个全局变量(BOOL g_bLiceseOK;),用于标识用户是否有合法的授权文件。 然后通过向导,增加函数OnBegin,下面是增加验证功能的OnBegin函数:

 //---------------------------------------------------------------------------
 // OnBegin
 //
 // The OnBegin event is called directly by the framework after the setup
 // initializes.
 //---------------------------------------------------------------------------
 function OnBegin()
      STRING strFile;
 begin
      // TO DO: you may change default non-UI setting, for example
      //
      // You may also perform your custom initialization steps, check requirements, etc.
      // 授权文件拷贝
      g_bLiceseOK = TRUE;
      if(!MAINTENANCE)  then
          if(FindFile(SRCDIR,"\\THIDFaceLicense.dat", strFile) <0)  then
              if(AskYesNo("没有找到THIDFaceLicense.dat授权文件,继续安装吗?", YES)=NO) then
                  abort; 
              else
                  g_bLiceseOK = FALSE;
              endif;
          endif;

          if(FindFile(SRCDIR,"\\THIDQualityLicense.dat", strFile) <0)  then
              if(AskYesNo("没有找到THIDQualityLicense.dat授权文件,继续安装吗?", YES)=NO) then
                  abort; 
              else
                  g_bLiceseOK = FALSE;
              endif;
          endif;
      endif;
 end;   

 这段代码执行后,我们就可以知道用户是不是有授权文件,根据授权文件的有无就可以执行后面的操作了,如果用户 拥有授权文件,那么在用户选择好安装路径和安装完运行环境后,我们就可以使用脚本将授权文件拷贝到用户的安装路径下, 通过向导增加函数OnFirstUIAfter,然后在该函数的最开始增加下面的代码:

if(g_bLiceseOK) then
      CopyFile(SRCDIR^"\\THIDFaceLicense.dat", TARGETDIR^"THIDFaceLicense.dat");
      CopyFile(SRCDIR^"\\THIDQualityLicense.dat", TARGETDIR^"THIDQualityLicense.dat");
 endif;

第四个任务 完美卸载

        细心的读者可能发现,前面制作的安装包在卸载的时候,安装路径文件夹还保存在用户的机器上。完美的安装包应该在执行卸载操作后, 使用户的机器和安装前基本相同,我们现在多了一个文件夹,还有我们在卸载的时候没有支持用户选择是否卸载我们的运行环境。同样, 这一部分我们也需要解决两个问题:1、如何卸载安装的文件,2、在哪里写卸载代码。我们需要使用脚本卸载的文件是我们放入支持路径下的所有文件, 和我们安装时使用的非安装包文件。本例中我们需要使用脚本卸载的文件是授权文件和VC运行环境,前者我们可以直接卸载, 后者有两种情况,该运行环境是我们的安装包安装的,我们需要提示用户是否卸载运行环境;但是如果该运行环境早于我们的安装, 我们就应该忽略该卸载过程。运行环境的卸载,我只写思路,有兴趣的可以自己完成:在安装时如果用户安装了指定的软件,将该安装信息记录到 目标机器的注册表中,卸载时读取该注册表项,确定用户是否安装了该环境,再进行后面的卸载操作。卸载VC2008运行环境可以通过执行 MsiExec.exe /quiet /X{9A25302D-30C0-39D9-BD6F-21E6EC160475} 来实现(我怎么知道的?研究注册表啊:-))。由于很多安装包都没有卸载 安装时使用的运行环境,这里就不进行详细描述了,如有需要伊妹儿我吧。

        卸载代码的位置就比较简单了,我直接上代码吧,使用脚本向导,增加函数OnMaintUIBefore,下面的代码示例了, 在卸载时首先移除授权文件以实现安装路径文件夹的卸载:

 //---------------------------------------------------------------------------
 // OnMaintUIBefore
 //
 // The OnMaintUIBefore event is called by the framework when the setup is
 // running in maintenance mode. By default this event displays UI that
 // allows the end user to add or remove features, repair currently
 // installed features or uninstall the application.
 //---------------------------------------------------------------------------
 function OnMaintUIBefore()
      NUMBER nResult, nType;
      STRING szTitle, szMsg, svDir, svResult, szCaption;
 begin
      // ...... 这个意思你懂的 :-)
      // Show Uninstall Confirmation Dialog
      if ( nType = REMOVEALL ) then
          DeleteFile(TARGETDIR^"THIDFaceLicense.dat");
          DeleteFile(TARGETDIR^"THIDQualityLicense.dat");
          //MessageBox("授权文件已经删除", 0);
          nResult = MessageBox( SdLoadString( IFX_MAINTUI_MSG ), MB_YESNO );
      if (nResult != IDYES ) then
      // ...... 这个意思你懂的 :-)

第五个任务 定制安装

        这个任务很轻松,很简单,前提是你仔细阅读过别人的脚本,还是一句话:在正确的地方做正确的事。这个实例中我们要求用户 将安装路径设置为系统盘以外的路径(但不强制),这些约束在OnFirstUIBefore函数中完成,过程如下:

  • 在OnFirstUIBefore的参数声明中增加char cInstDir,cSysDir;
  • 在初始化部分将nSetupType的值修改为CUSTOM,切记;
  • 注释掉Dlg_SetupType里面的代码;
  • 修改Dlg_SdAskDestPath后的的代码如下:
     
    //INSTALLDIR="D:\\Program Files\\MatchEngine"; //这样可以改变原始安装路径
     nResult = SdAskDestPath(szTitle, "由于比对服务器的本地缓存文件将占用较多的磁盘空间,强烈建议将比对引擎安装到系统盘外的磁盘分区,以保证系统的正常运行。", INSTALLDIR, 0);
     //if (nResult = BACK) goto Dlg_SetupType; 
     if (nResult = BACK) goto Dlg_SdRegisterUser;
     cInstDir = STRTOCHAR(INSTALLDIR); 
     cSysDir = STRTOCHAR(WindowsFolder);
     if(cInstDir=cSysDir) then
     nResult = AskYesNo("你真的要把比对引擎安装到系统盘吗?", NO );
     if(NO=nResult) goto Dlg_SdAskDestPath; 
     endif;
    

  • 修改Dlg_SQL后面的代码如下:
     nResult = OnSQLLogin( nResult );
     //if( nResult = BACK ) then
     //   if (!bCustom) then
     //       goto Dlg_SetupType;
     //   else
     //       goto Dlg_SdFeatureTree;
     //   endif;
     //endif; 
     if( nResult = BACK ) then
          goto Dlg_SdFeatureTree;
     endif;
    
  • 接下来的任务就是进行安装包的验证了。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值