zoukankan      html  css  js  c++  java
  • InstallShield学习笔记三:脚本(2)

    5.设置安装模式

    InstallScript MSI不足:

    在InstallScript MSI中,在OnFirstUIBefore()执行完成后,即安装完成,这个时候需要做后续的操作,如写注册表等,这些操作要在OnFirstUIAfter()中执行。

    如果此时点击取消,然后在此安装时,InstallShield会提示先卸载之前的安装,这个体验非常不好,而且InstallScript MSI还没有办法修改。

    而在InstallScript 提供了一个逻辑条件,即OnShowUI(),这个可以自己修改安装模式,代码如下

    function OnShowUI()
    BOOL    bMaintenanceMode, bUpdateMode;
    string    szIgnore, szTitle;
    begin
            
            // Enable dialog caching
            Enable( DIALOGCACHE );
            
            // Determine what events to show.
            bUpdateMode    = FALSE;
            bMaintenanceMode = FALSE;
        
            // Remove this to disabled update mode.
            if( UPDATEMODE ) then
                bUpdateMode = TRUE;
            endif;
    
            // Remove this to disable maintenance mode.
            if ( MAINTENANCE ) then
                bMaintenanceMode = TRUE;
            endif;
    
            // Show appropriate UI
    
            // TODO: Enable if you want to enable background etc.
            //if ( LoadStringFromStringTable( "TITLE_MAIN", szTitle ) < ISERR_SUCCESS ) then // Load the title string.
            //    szTitle = IFX_SETUP_TITLE;
            //endif;
            //SetTitle( szTitle, 24, WHITE );
            //Enable( FULLWINDOWMODE );                           
            //Enable( BACKGROUND );
            //SetColor( BACKGROUND, RGB( 0, 128, 128 ) );
    
            if( bUpdateMode ) then
                OnUpdateUIBefore();
            else
                if ( bMaintenanceMode ) then
                    OnMaintUIBefore();
                else
                    OnFirstUIBefore();
                endif;
            endif;
    
            // Move Data
            OnMoveData(); // 这里可以安装,也可以卸载组件
            
    
    if( bUpdateMode ) then OnUpdateUIAfter(); else if ( bMaintenanceMode ) then OnMaintUIAfter(); else OnFirstUIAfter(); endif; endif; // Disable dialog caching Disable(DIALOGCACHE); end;

    分析:

    (1)可以看到可以显示有3中模式:OnUpdateUIBefore,OnMaintUIBefore,OnFirstUIBefore(对应有After),分别表示升级,维护(卸载,重安装),首次安装。

    (2)OnMoveData()。这个是整个方法最重要的部分,表示数据安装或者卸载。具体使用会在后面分析。

    如果我们不需要用户升级,可以将OnUpdateUIBefore()替换为OnFirstUIBefore(),OnUpdateUIAfter()替换为OnFirstUIAfter()不要删除,替换即可。修改后,即使用户安装中途取消,再次运行安装程序时,也是首次安装的状态(表现为:如果在在安装包中选择弹出语言选择框,此时这个语言选择框也会弹出。。)

    6.在卸载组件中OnMoveData()的使用

    在第5点中展示了使用OnMoveData,这里要说下使用过程中要注意到东西。

    代码:

    function OnMoveData()
    number    nResult, nMediaFlags;
    begin
    
        // Don't install the DISK1COMPONENT if MAINT_OPTION_NONE was specified.
        if( MAINT_OPTION = MAINT_OPTION_NONE ) then
            FeatureSelectItem( MEDIA, DISK1COMPONENT, FALSE );
        endif;
    
        // Updated in 11.5, disable the cancel button during file transfer unless
        // this is non-maintenance mode or repair mode.
        if( MAINTENANCE && ( !REINSTALLMODE || UPDATEMODE ) ) then
            Disable( CANCELBUTTON );
        endif;
    
        // Show Status
        // Note: Start status window at 1 in case CreateInstallationInfo call
        // is lengthy.
        SetStatusWindow( 1, "" );
        Enable( STATUSEX );
        StatusUpdate( ON, 100 );
    
        // Create the uninstall infomation (after displaying the progress dialog)
        // Don't create uninstall information if MAINT_OPTION_NONE was specified.
        if( MAINT_OPTION != MAINT_OPTION_NONE ) then
            CreateInstallationInfo();
        endif;
    
        // Move Data
        nResult = FeatureTransferData( MEDIA );
        
        // Moved in 11.0, Check for failure before creating uninstall key.
        // Handle move data error and abort if error occured.
        if( nResult < ISERR_SUCCESS ) then
            OnComponentError();
            abort;
        endif;        
    
        // Create uninstall key, if DISK1COMPONENT was installed.
        if( IFX_DISK1INSTALLED ) then
    
            // Store text-subs for maintenance mode later, only do this when
            // disk 1 is installed. Note that any text-subs that are updated after
            // this call will not be remembered during maintenance mode.
            FeatureSaveTarget("");
    
            // Write uninstall information.
            MaintenanceStart();
    
            // Customize Uninstall Information
            OnCustomizeUninstInfo();
    
        endif;
    
        // Disable Status
        Disable( STATUSEX );
    
    end;

    这里最重要的是FeatureTransferData(MEDIA)这个使用。

    这个方法可以查看帮助文档,安装和卸载时是不一样的。

    安装:Installs features that are selected(安装只勾选的组件Feature)

    卸载:Uninstalls features that are not selected and are currently installed(卸载不勾选的组件Feature)。

    问题来了:

    在卸载时,即调用OnMaintUIBefore()的时候,调用的是nResult = SdFeatureTree( szTitle, szMsg, TARGETDIR, "", -1 );

    这样会出现的一个现象是:在卸载的时候,勾选的组件卸载不掉,不勾选的反而卸载了(这个根本原因是组件重新安装)。

    (这里只贴上OnMaintUIBefore()部分代码)

    Dlg_SdFeatureTree:
        if ( nType = MODIFY ) then
            szTitle = "";
            szMsg = SdLoadString( SD_STR_COMPONENT_MAINT_MSG );
            nResult = SdFeatureTree( szTitle, szMsg, TARGETDIR, "", -1 );
            if ( nResult = BACK ) goto Dlg_Start;
        endif;

     解决办法:反选组件。

    使用FeatureSelectItem()来控制。思路是:如果只卸载Feature1,后台设置Feature1为不勾选状态,而将Featreu2设置为勾选状态;Feature2同理。

    示例代码如下:

    function OnMoveData()
    number    nResult, nMediaFlags;
    begin
    
        …………
    // Show Status
        // Note: Start status window at 1 in case CreateInstallationInfo call
        // is lengthy.
        SetStatusWindow( 1, "" );
        Enable( STATUSEX );
        StatusUpdate( ON, 100 );
    
        // Create the uninstall infomation (after displaying the progress dialog)
        // Don't create uninstall information if MAINT_OPTION_NONE was specified.
        if( MAINT_OPTION != MAINT_OPTION_NONE ) then
            CreateInstallationInfo();
        endif;
        
          // 只有卸载时才需要这样配置,安装不需要
        if(REMOVEONLY) then
          // 只卸载Feature1,将Feature1设置为不选状态,将Feature2设置为选中状态
           if(bSelectFeature1 && !bSelectFeature2) then 
          FeatureSelectItem(MEDIA,
    "DefaultFeature\NewFeature2", TRUE);   FeatureSelectItem(MEDIA, "DefaultFeature\NewFeature1", FALSE);
        // 只卸载Feature2,将Feature2设置为不选状态,将Feature1设置为选中状态   elseif (bSelectFeature2 && !bSelectFeature1) then
          FeatureSelectItem(MEDIA,
    "DefaultFeature\NewFeature1", TRUE);   FeatureSelectItem(MEDIA, "DefaultFeature\NewFeature2", FALSE);   endif; endif; // Move Data nResult = FeatureTransferData( MEDIA ); // Moved in 11.0, Check for failure before creating uninstall key. // Handle move data error and abort if error occured. if( nResult < ISERR_SUCCESS ) then OnComponentError(); abort; endif; ………… end;

    7.运行第三方程序

    在InstallShield中,提供给调用exe,bat等文件。

    LaunchAppAndWait ( szProgram, szCmdLine, nOptions );

    代码示例:

    function OnFirstUIAfter()
        STRING szTitle, szMsg1, szMsg2, szOpt1, szOpt2;
        NUMBER bvOpt1, bvOpt2;
        STRING szProgram, szCmd;
    begin
    
        ShowObjWizardPages(NEXT);
        
        szTitle = "";
        szMsg1 = ""; 
        szMsg2 = "";
        szOpt1 = "";
        szOpt2 = "";
        bvOpt1   = FALSE;
        bvOpt2   = FALSE;    
        
        szProgram = WINDIR ^ "System32\PING.exe";
         // szProgram = SUPPORTDIR ^ "test.bat"; // 如果使用自定义的bat,需要在Support Files/Billboards中存入bat文件
        szCmd = "www.baidu.com";
        
        LaunchAppAndWait (szProgram, szCmd, LAAW_OPTION_NOWAIT|LAAW_OPTION_HIDDEN);
        nResult = LAAW_PARAMETERS.nLaunchResult;    
        
        //{{IS_SCRIPT_TAG(Dlg_SdDinishEx)    
        if ( BATCH_INSTALL ) then
            SdFinishReboot ( szTitle , szMsg1 , SYS_BOOTMACHINE , szMsg2 , 0 );
        else
            SdFinish ( szTitle , szMsg1 , szMsg2 , szOpt1 , szOpt2 , bvOpt1 , bvOpt2 );
        endif;
        //}}IS_SCRIPT_TAG(Dlg_SdDinishEx)    
    end;

    这里基本上展示了LaunchAppAndWait 的用法,重点记录的是获取返回值,这个值在bat中通过使用exit()获取返回值,如exit(-1)。

    8.取消安装提示信息修改

    在安装和卸载过程中,如果点击取消,此时会发现弹出的信息一模一样,默认是显示取消安装的信息。试想,在取消卸载时,提示这样的信息会让用户一头雾水。

    这时候需要修改取消过程中的信息,修改OnCanceling()

    原始代码:

    function OnCanceling()
        STRING szTitle, szMsg1, szMsg2, szOpt1, szOpt2;
        NUMBER bvOpt1, bvOpt2;
    begin
        if (IDYES = SprintfBox(MB_YESNO|MB_ICONEXCLAMATION|MB_DEFBUTTON2, SdLoadString(SD_STR_ONCANCELING_TITLE), SdLoadString(SD_STR_ONCANCELING_CONFIRM_MSG))) then
            //Close the current dialog.
            EndCurrentDialog();
            //Display Finish dialog.
            szTitle = "";    
            szMsg1 = SdLoadString( SD_STR_ONCANCELING_FINISH_MSG1 );
            szMsg2 = SdLoadString( SD_STR_ONCANCELING_FINISH_MSG2 );    
            szOpt1 = "";
            szOpt2 = "";
            bvOpt1   = FALSE;
            bvOpt2   = FALSE;
            SdFinish ( szTitle, szMsg1, szMsg2 , szOpt1, szOpt2, bvOpt1, bvOpt2 );                       
            
            abort;
        endif;
    end;

    修改后的代码:

    技巧:这里使用“@”可以获取资源文件中的信息。

    修改后代码:

    function OnCanceling()
        STRING szTitle, szMsg1, szMsg2, szOpt1, szOpt2;
        NUMBER bvOpt1, bvOpt2;
        STRING szBoxTitle, szBooxMsg;
    begin
    
        if(MAINTENANCE) then
            szBoxTitle = SdLoadString(SD_STR_ONCANCELING_TITLE);
            szBooxMsg = SdLoadString(SD_STR_ONCANCELING_CONFIRM_MSG);
            
            // 这个与弹出框没有关系,这里呈现的地方是退出向导页面,默认是安装完成
            szMsg1 = SdLoadString( SD_STR_ONCANCELING_FINISH_MSG1 ); 
            szMsg2 = SdLoadString( SD_STR_ONCANCELING_FINISH_MSG2 );   
        else
            szBoxTitle = @UNINSTALL_BOX_TITLE;
            szBooxMsg = @UNINSTALL_BOX_MSG;
            
            // 这个与弹出框没有关系,这里呈现的地方是退出向导页面
            szMsg1 = @UNINSTALL_TITLE;
            szMsg2 = @UNINSTALL_MSG;
        endif;
            
    
        if (IDYES = SprintfBox(MB_YESNO|MB_ICONEXCLAMATION|MB_DEFBUTTON2, szBoxTitle, szBooxMsg)) then
            //Close the current dialog.
            EndCurrentDialog();
            //Display Finish dialog.
            szTitle = "";  
            szOpt1 = "";
            szOpt2 = "";
            bvOpt1   = FALSE;
            bvOpt2   = FALSE;
            SdFinish ( szTitle, szMsg1, szMsg2 , szOpt1, szOpt2, bvOpt1, bvOpt2 );                       
            
            abort;
        endif;
    end;

    效果:

    image  image

  • 相关阅读:
    《ASP.NET Core 高性能系列》致敬伟大的.NET斗士甲骨文!
    ThreadLocal<T>的是否有设计问题
    从.NET和Java之争谈IT这个行业
    自建型呼叫中心
    托管型呼叫中心
    数字语音记录仪3.0
    模拟电话录音系统2.0
    easyui-combobox 下拉菜单 多选 multiple
    利用easyui-combotree实现 下拉菜单 多选功能(带多选框)
    eclipse项目导入 idea中
  • 原文地址:https://www.cnblogs.com/winlrou/p/3965515.html
Copyright © 2011-2022 走看看