InstallShield学习笔记三:脚本(2)

摘要:
如果此时点击取消,然后在此安装时,InstallShield会提示先卸载之前的安装,这个体验非常不好,而且InstallScriptMSI还没有办法修改。而在InstallScript提供了一个逻辑条件,即OnShowUI(),这个可以自己修改安装模式,代码如下functionOnShowUI()BOOLbMaintenanceMode,bUpdateMode;stringszIgnore,szTitle;begin//EnabledialogcachingEnable;//Determinewhateventstoshow.bUpdateMode=FALSE;bMaintenanceMode=FALSE;//Removethistodisabledupdatemode.ifthenbUpdateMode=TRUE;endif;//Removethistodisablemaintenancemode.ifthenbMaintenanceMode=TRUE;endif;//ShowappropriateUI//TODO:Enableifyouwanttoenablebackgroundetc.//ifthen//Loadthetitlestring.//szTitle=IFX_SETUP_TITLE;//endif;//SetTitle;//Enable;//Enable;//SetColor;ifthenOnUpdateUIBefore();elseifthenOnMaintUIBefore();elseOnFirstUIBefore();endif;endif;//MoveDataOnMoveData();//这里可以安装,也可以卸载组件ifthenOnUpdateUIAfter();elseifthenOnMaintUIAfter();elseOnFirstUIAfter();endif;endif;//DisabledialogcachingDisable;end;分析:可以看到可以显示有3中模式:OnUpdateUIBefore,OnMaintUIBefore,OnFirstUIBefore,分别表示升级,维护,首次安装。

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();
            elseOnFirstUIBefore();
            endif;
        endif;

        //Move Data
        OnMoveData(); //这里可以安装,也可以卸载组件
        

if( bUpdateMode ) then OnUpdateUIAfter(); else if( bMaintenanceMode ) then OnMaintUIAfter(); elseOnFirstUIAfter(); 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 ) gotoDlg_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);
    elseSdFinish ( 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 );   
    elseszBoxTitle =@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;

效果:

imageimage

免责声明:文章转载自《InstallShield学习笔记三:脚本(2)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Failure to find xxx in xxx was cached in the local repository, resolution will not be reattempted until the update interval of nexus has elapsed or updates are forced @ xxxpiwik学习下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

随便看看

N1盒子刷Armbian整理

我买了一把亚美尼亚刷子,记录了投掷的过程。本文基于《斐济N1–完美机器刷臂教程》和《斐济N1刷臂5.64》,结合自身实际操作中遇到的问题。为了使斐济N1的所有硬件都能被armbian正常调度,需要将一组dtb文件适配到斐济N1。目前,斐济N1的dtb文件已被armbian包含在官方源代码库中,但Linux在使用时的负载将非常高,因此热心的网友为ARMBIAN...

Xmind常用快捷键

快捷鍵(WINDOWS)快捷鍵(MAC)描述Ctrl+NCommand+N建立新工作簿Ctrl+OCommand+O开启工作簿Ctrl+SCommand+S储存目前工作簿Ctrl+Shift+SCommand+Shift+S储存全部工作簿Ctrl+WCommand+W关闭目前工作簿Ctrl+Shift+WCommand+Shift+W关闭全部工作簿Ctrl+...

【转】MUD教程--巫师入门教程4

在MUD中,为了解决定时触发某种现象,一般有两种方法,一种是通过call_out()延时呼叫,另一种就是通过心跳。于是,对于要跨起离线前后的象做牢这类的事,大多都是采用condition。附:由于大多数MUD里的心跳是每两秒调一次,5+random是5至14次,因此可以看出每一个condition被调用的时间是平均19秒。然后它会按照condition的名字...

c++ 发送消息,模拟拖拽文件

=NULL)28{29LPSTRpszRemote=VirtualAllocEx;30if31{32::SendMessage;33bResult=TRUE;34}35}36}3738if39{40delete[]pBuf;41pBuf=NULL;42}43 returnbResult;44}在调用此函数之前,首先打开接受拖动的进程ShellExecute;...

windows 常用命令行操作

目录操作˃pwd打印当前工作目录,通过此关键词可以查看当前所处的路径˃cd更改目录,用于多个目录之间的切换具体输入:cd目录名cd目录名/子目录名(可通过此方式到达最底层的目录)cd~(返回home目录)cd..(返回上一级目录)cd../..(返回上两级目录)cd盘符名:(不同盘符间跳转,cd后面跟上路径则可实现精准跳转)˃mkdir创建目录具体输入:mk...

rz上传文件及出错解决方案

原始链接:https://blog.csdn.net/yjk13703623757/article/details/87083997单独使用rz命令时有两个问题:上载中断和文件更改。解决方案是使用rz be进行上传,并在弹出对话框中删除“UploadfilesasASCII”之前的复选框。如果使用不带参数的rz命令上传一个大文件,则在上传过程中通常会中断。很...