直接图文:注:
使用的模板为InstallScript MSI Project
Installation Designer -->User Interface -->Dialogs -- >All Dialogs -->右键 New Dialog -- >下一步 NewScriptBasedDialog
图1:
双击自定义的对话框,进入对话框设计器,然后通过设计器来绘制自定义对话框。
图2:
图3:
View -->Maximize 使设计器最大化
此时要注意几个属性值:1 点击窗体,显示右侧属性 Resource Identifier需要根据需要自己定义,此值会在代码中使用到。需特别注意。为防止与其他的Id冲突,可设置较大一点,其后的ID会根据此ID自动递增。
图4:
新建一个field,其Control Identifier值会根据Resource Identifier自增(窗体的Id叫 Resource Identifier,而field的Id就称为Control Identifier)然后根据实际需要设计窗体布局。以下为设计好的对话框。
图5:
好,现在界面部分已经完成,需要进入脚本操作。
图6:
选择Setup.Rul --> Before Move Data -- OnFirstUIBefore.
注意此函数在InstallScript MSI Project 中是用来控制对话框的显示顺序,同时可以将自定义的窗体插入到显示序列中。
图7:
代码如下
function OnFirstUIBefore()
NUMBER nResult, nSetupType, nvSize, nUser;
STRING szTitle, szMsg, szQuestion, svName, svCompany, szFile;
STRING szLicenseFile;
LIST list, listStartCopy;
BOOL bCustom;
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));
SHELL_OBJECT_FOLDER = @PRODUCT_NAME;
nSetupType = TYPICAL;
Dlg_SdWelcome:
szTitle = "";
szMsg = "";
nResult = SdWelcome(szTitle, szMsg);
if (nResult = BACK) goto Dlg_SdWelcome;
szTitle = "";
svName = "";
svCompany = "";
Dlg_SdCustomerInformation:
nResult = SdCustomerInformation(szTitle, svName, svCompany, nUser);
if (nResult = BACK) goto Dlg_SdWelcome;
Dlg_SetupType:
szTitle = "";
szMsg = "";
nResult = SetupType(szTitle, szMsg, "", nSetupType, 0);
if (nResult = BACK) then
goto Dlg_SdCustomerInformation;
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_ChangeConfig:
nResult = ChangeConfig("", "" );
if( nResult = BACK ) then
goto Dlg_SQL;
endif;
Dlg_SdStartCopy:
szTitle = "";
szMsg = "";
listStartCopy = ListCreate( STRINGLIST );
//The following is an example of how to add a string(svName) to a list(listStartCopy).
//eg. ListAddString(listStartCopy,svName,AFTER);
nResult = SdStartCopy( szTitle, szMsg, listStartCopy );
ListDestroy(listStartCopy);
if (nResult = BACK) then
goto Dlg_SQL;
endif;
// setup default status
Enable(STATUSEX);
return 0;
end;
代码解释:
Dlg_ChangeConfig:
nResult = ChangeConfig("", "" );
if( nResult = BACK ) then
goto Dlg_SQL;
endif;
这段是自己添加的自定义代码,作用是在窗体Dlg_SQL完成后,显示自定义窗体(名称为ChangeConfig)
nResult = ChangeConfig("", "" );
ChangeConfig是自定义的函数,定义及实现如下:
首先需要在代码的头位置定义函数:
export prototype ChangeConfig(string, string);
然后 定义函数体:
function ChangeConfig(szTitle, szMsg)
string szDlg, szDialogName, szDLLName, szDialog;
number nId, hInstance, hwndParent, nResult;
HWND hwndDlg;
BOOL bDone;
begin
// Specify a name to identify the custom dialog in this installation.
szDlg = "ChangeConfig";
// ensure general initialization is complete
if( !bSdInit ) then
SdInit();
endif;
szDialogName = "NewDialog";
hInstance = 0;
szDLLName = "";
szDialog = "";
hwndParent = 0;
//szDlg是自定义窗体的名称(参见图1), 10000为此窗体的Resource Identifier.
nResult = EzDefineDialog(szDlg, ISUSER, "", 10000 );
// Initialize the indicator used to control the while loop.
bDone = FALSE;
// Loop until done.
while (!bDone)
// Display the dialog and return the next dialog event.
nId = WaitOnDialog(szDlg);
// Respond to the event.
switch(nId)
case DLG_INIT:
// No initialization is required for this example.
case NEXT:
getCtrlText();
nId = NEXT;
bDone = TRUE;
case BACK:
nId = BACK;
bDone = TRUE;
case DLG_ERR:
SdError( -1, "Errrrrrrr" );
nId = -1;
bDone = TRUE;
case DLG_CLOSE:
SdCloseDlg( hwndDlg, nId, bDone );
default:
// check standard handling
if(SdIsStdButton( nId ) && SdDoStdButton( nId )) then
bDone = TRUE;
endif;
endswitch;
endwhile;
// Cleanup Dialog
EndDialog( szDlg );
ReleaseDialog( szDlg );
SdUnInit();
// record data produced by this dialog
if( MODE = RECORDMODE ) then
endif;
return nId;
end;
代码注释:
case NEXT:
getCtrlText();
nId = NEXT;
bDone = TRUE;
即在窗体点击下一步时执行自定义的代码。
getCtrlText代码如下
prototype getCtrlText();
export prototype FNModifyProperty(string, int, string);
#define DLG_SERVICEIP_ID 10001
#define DLG_WEBIP_ID 10009
#define DLG_MAILSERVERIP_ID 10011
#define DLG_MAILPORT_ID 10017
#define DLG_ENABLESSL_ID 10024
#define DLG_MAILUSER_ID 10020
#define DLG_MAILPWD_ID 10019
#define DLG_MAILADMINADDRESS_ID 10021
#define DLG_TARGETENV_ID 10028
#define DLG_TARGETENVNAME_ID 10029
function getCtrlText()
string szDialogName, svUser, strRtn;
begin
szDialogName = "ChangeConfig";
//ServiceIP
FNModifyProperty(szDialogName, DLG_SERVICEIP_ID, "C_SERVICEIP");
//WebIP
FNModifyProperty(szDialogName, DLG_WEBIP_ID, "C_WEBIP");
//C_MAILSERVERIP
FNModifyProperty(szDialogName, DLG_MAILSERVERIP_ID, "C_MAILSERVERIP");
//C_MAILPORT
FNModifyProperty(szDialogName, DLG_MAILPORT_ID, "C_MAILPORT");
//ServiceIP
FNModifyProperty(szDialogName, DLG_ENABLESSL_ID, "C_ENABLESSL");
//WebIP
FNModifyProperty(szDialogName, DLG_MAILUSER_ID, "C_MAILUSER");
//C_MAILSERVERIP
FNModifyProperty(szDialogName, DLG_MAILPWD_ID, "C_MAILPWD");
//C_MAILPORT
FNModifyProperty(szDialogName, DLG_MAILADMINADDRESS_ID, "C_MAILADMINADDRESS");
//ServiceIP
FNModifyProperty(szDialogName, DLG_TARGETENV_ID, "C_TARGETENV");
//WebIP
FNModifyProperty(szDialogName, DLG_TARGETENVNAME_ID, "C_TARGETENVNAME");
end;
function FNModifyProperty(szDialogName, id, propertyId)
string tempStr;
begin
CtrlGetText(szDialogName, id, tempStr);
//MessageBox(tempStr, INFORMATION);
MsiSetProperty(ISMSI_HANDLE,propertyId,tempStr);
end;
代码注释
DLG_XXXX_ID为图5的文本框的Id.
可以注意到,代码中关键的一个方法是FNModifyProperty,此方法的目的是为了将文本框的值,赋给自定义属性(可以理解为IS的全局变量,此变量可以在后面的XML变更时,被引用到)。
属性的定义如下:
C_XXXX与图5的文本框一一对应,即在自定义文本框点击下一步时,将文本框的值赋给全局变量C_XXXX。注:文本框的值只在OnFirstUIBefore方法的对应显示窗体的步骤中才能够获取到。
此时自定义的窗体的值已经被保存到IS的可访问属性(全局变量)中, 下面就是对此属性值的应用了。我们获取这些属性的目的主要是为了修改我们应用程序的配置文件信息。以下将演示如何引入Config,并将Config的值用属性值进行替换。
SystemConfiguration -->XML Files Changes
选择右侧的 XML Fiels,右键 Import(导入)
选择需要变更的节点。
选择文件名, 修改此配置文件在安装环境的目录。
然后选择到对应的节点。
然后将需要修改的部分如192.168.0.116替换为[C_SERVICEIP]([]表示属性,IS会在生成时自动将[xxxx]用xxxx的属性值替换)
最后,切换到Advanced,将Set element content选项选中。
最后编译生成安装包,然后在目标环境运行安装包。
安装完毕后,会看到对应的配置文件会根据填写的值自动修改。
OK, 完成。