正式会员享受无限制浏览网站功能和高速网盘下载,赶快加入本站吧!
您需要 登录 才可以下载或查看,没有账号?立即注册
x
1 几个技术问题介绍
1.1 数据库设置
在安装程序中设置数据库,有两种方法:一种采用命令行附加数据库文件,一种是通过SQL Script脚本创建数据库,对于编写SQL Script过于复杂,或创建数据库时间过长时建议采用第一种方法。
1.1.1 命令行附加数据库
1. 将数据库文件(a_data.mdf和a_log.ldf)插入Support Files中;
2. 定义变量:
- STRING psvSQLsvr, psvSQLusr, psvSQLpwd;
- BOOL bvWindowsLogin;
复制代码
3. 定义CreateDataBase函数:
- prototype CreateDataBase(STRING,STRING,STRING);
复制代码
4. 编写CreateDataBase函数:
- function CreateDataBase(svSQLsvr,svSQLusr,svSQLpwd)
- STRING szWaitTxt,szdatabase,path,path3;
- begin
- path=TARGETDIR^"Data""a_data.MDF";
- path3=TARGETDIR^"Data""a_log.LDF";
- szWaitTxt=" 正在创建数据库....";
- SdShowMsg (szWaitTxt, TRUE);
- Delay(3);
- CopyFile(SUPPORTDIR^"a_data.MDF",path);
- CopyFile(SUPPORTDIR^"a_log.LDF",path3);
- szdatabase = "/U "+svSQLusr+" /P "+svSQLpwd+" /S "+svSQLsvr+" /Q ""exec sp_attach_db N'a' , N'"+path+"',N'"+path3+"'""";
- if (LaunchAppAndWait("osql.exe", szdatabase,WAIT)<0) then;
- MessageBox ("数据库创建失败!请确您的系统中已安装 Microsoft SQL Server 2000."n如仍无法解决,请联系系统供应商!",SEVERE);
- SdShowMsg (szWaitTxt, FALSE);
- return -1;
- endif;
- end;
复制代码
5. 获取数据库的登录信息,如果没有创建数据库的脚本,安装程序不会弹出SQL登录验证界面,需要编写代码:
- Prototype number SQLLogin(); //定义登录函数
- function SQLLogin ()
- number nResult, nSize;
- STRING sMessage, sTemp;
- begin
- Dlg_Sql:
- SQLRTInitialize2 ();
- nResult = SQLServerSelectLogin(psvSQLsvr, psvSQLusr, psvSQLpwd, bvWindowsLogin );
- if (nResult = BACK) return BACK;
- nSize=MAX_PATH;
- MsiGetProperty( ISMSI_HANDLE, "IS_SQLSERVER_STATUS", sTemp, nSize );
- if(sTemp!="0") then
- nSize = _MAX_PATH;
- MsiGetProperty( ISMSI_HANDLE, "IS_SQLSERVER_STATUS_ERROR", sMessage, nSize );
- if( nSize = 0 ) then
- sMessage = SdLoadString( IDS_IFX_SQL_ERROR_LOGIN_FAILED );
- endif;
- MessageBox( sMessage, MB_OK );
- goto Dlg_Sql;
- endif;
- return 0;
- end;
复制代码
6. 在OnFirstUIBefore事件中调用SQLLogin函数:
- Dlg_SdSQL:
- nResult = SQLLogin();
- if (nResult = BACK) goto Dlg_Custom;
复制代码
7. 在OnEnd事件中调用CreateDataBase函数:
- function OnEnd()
- begin
- if !MAINTENANCE then
- CreateDataBase(psvSQLsvr,psvSQLusr,psvSQLpwd); // 创建和 优化数据库
- endif;
- end;
复制代码
1.1.2 SQL Script
在Installation Designer中的SQL Scripts插入创建数据库的脚本即可,值得注意的是脚本中的文本替换,如果脚本中有安装前未知信息(在安装过程中输入的),如数据库的安装路径,使用软件的公司名称等等,需要使用文本替换,方法如下:
1. 创建数据库的脚本片段
- CREATE DATABASE [test] ON (NAME = N'test_Data', FILENAME = N'%INSTALL_DIR%DATA"test_Data.MDF' , SIZE = 4, FILEGROWTH = 0) LOG ON (NAME = N'test_Log', FILENAME = N'%INSTALL_DIR%DATA"test_Log.LDF' , SIZE = 4, FILEGROWTH = 10%)
- GO
- use test
- GO
- INSERT INTO [dbo].[use_company] ( [company _name])
- VALUES ('%MY_COMPANY_NAME%')
复制代码
2. 在Installation Designer中的Property Manager添加一个MY_COMPANYNAME的属性,如下图所示
3. 在OnFirstUIBefore事件中添加代码:
- Dlg_UserInfo:
- szMsg = "请正确输入用户名称及公司名称,以便本系统显示的信息正确!";
- nResult = SdRegisterUser(szTitle, szMsg, szUserInfo, szCompanyName);
- MsiSetProperty(ISMSI_HANDLE,"MY_COMPANYNAME", szCompanyName);
- if (nResult = BACK) goto Dlg_SdLicense;
复制代码
4. 在Installation Designer中的SQL Scripts的Text Replacement页面添加两个替换参数,如下图所示:
1.2 InstallScirpt调用动态运行库中的函数
安装过程中有些设置是InstallShield无法做到的,需要其他的编程软件实现,其他的编程软件可以编写成可执行的应用程序(EXE文件),通过LaunchApp和LaunchAppAndWait调用,也可以编写成动态运行库(DLL文件),InstallShield调用其中的函数,我使用的是Borland Delphi编程软件,我编写了一个将安装文件夹设置为FTP虚拟目录的动态运行库,在InstallShield中调用。
Delphi的源代码如下:
- library FtpSetup;
- uses
- SysUtils, Classes, COMOBJ, Variants;
- {$R *.res}
- procedure FtpSet(siteName, appPath: PCHAR);stdcall;
- var
- FTPSite, FTPServer, FTPRoot, FTPVDir: Variant;
- newSiteName, newAppPath:string;
- begin
- newSiteName:= siteName;
- newAppPath:= appPath;
- FTPSite := CreateOleObject('IISNamespace');
- FTPSite := FTPSite.GetObject('IIsFtpService', 'localhost/MSFTPSVC');
- FTPServer := FTPSite.GetObject('IIsFtpServer', '1');
- FTPRoot := FTPServer.GetObject('IIsFtpVirtualDir', 'Root');
- FTPVDir := FTPRoot.Create('IIsFtpVirtualDir', newSiteName);
- FTPVDir.Path := newAppPath;
- FTPVDir.AccessRead := true;
- FTPVDir.AccessWrite := true;
- FTPVDir.SetInfo;
- FTPSite := Unassigned;
- FTPServer := Unassigned;
- FTPRoot := Unassigned;
- FTPVDir := Unassigned;
- end;
- exports
- FtpSet;
- begin
- end.
复制代码
InstallScript 脚本如下:
- 函数定义
- prototype stdcall FtpSetup.FtpSet (POINTER,POINTER);
- 调用函数
- DLL_FILE= SUPPORTDIR^"FtpSetup.dll";
- nResult = UseDLL (DLL_FILE);
- if (nResult = 0) then
- svString1 = "drawingfile";
- svString2 = TARGETDIR^"DrawingFilePath";
- psvString1 = &svString1;
- psvString2 = &svString2;
- FtpSet(psvString1,psvString2);
- UnUseDLL (DLL_FILE);
- else
- MessageBox("创建FTP服务失败,请手工设置。",SEVERE);
- endif;
复制代码
值得注意的是函数的编写及调用都采用stdcall方式。
1.3 自定义窗体
1.3.1 Basic MSI Project工程项目
1. 创建自定义窗体,可参考标准窗体的各种设置,主要是窗体Behavior的设置,下面以一个例子说明创建过程;
2. 创建一个记录登录服务器的信息的自定义窗体,该窗体需要录入服务器的IP地址、用户名及口令,将录入信息记录到XML文件中;
3. 如下图所示,在User Interface的Dialogs的All Dialogs点击右键,选择New Dialgo菜单,进入自定义窗体向导;
4. 选择Blank Dialog创建一个空白窗体,重命名NewDialog1,如ServerLogin;
5. 如下图所示选择ServerLogin下的Chinse(Simplified)节,可设计此窗体;
6. 添加三个Text Area,分别将Text属性更改为服务器IP:、用户名:及口令:,添加三个Edit Field,分别录入Property Name(属性名称)为MY_SERVER_IP、MY_SERVER_USER及MY_SERVER_PWD, 将口令的录入框的Password属性的值更改为True,添加三个Push Button,分别是上一步、下一步及取消,如下图所示:
7. 如果想将此窗体插入CustomerInformation窗体与SetupType之间,可选择CustomerInformation的Behavior的Next按钮,如下图所示,将Event的NewDialog的Argument更改为ServerLogin窗体;
8. 选择ServerLogin的Behavior的Next按钮 ,新增一个NewDialog事件,将Argument更改为SetupType窗体,Condition更改为1,同理在上一步按钮中添加返回CustomerInformation窗体的事件,在取消按钮中添加Event为SpawinDialog,Argument为CancelSetup,Condiiton为1,如下图所示:
9. 可以在Behavior and Logic中的Custom Actions and Sequences中可以看出窗体的执行顺序,如下图所示:
10. 在XML File Changes节中添加记录信息,这里不再详述。
1.3.2 InstallScript MIS Project工程项目
1. 创建自定义窗体需要注意在InstallScript中如何调用自定义窗体,并将窗体的属性复制公共属性,下面以一个例子说明调用;
2. 创建一个记录登录服务器FTP的信息的自定义窗体,该窗体需要录入服务器的IP地址、FTP端口、FTP用户名及口令,将录入信息记录到XML文件中;
3. 在User Interface的Dialogs的All Dialogs点击右键,选择New Dialgo菜单,进入自定义窗体向导,选择Blank Dialog创建一个空白窗体,重命名NewDialog1,如SdComputerInfo,编辑窗体如下图所示:
4. 在Direct Editor的Dialog中查出该窗体的ID,我创建的这个自定义窗体的ID为12011,在Direct Editor的Control中查出各控件的ID;
5. 在Property Manager中新建四个属性LOCALHOST、LOGINUSER、LOGINPWD、FTPPORT;
6. 在InstallScript中新建一个名为computerinfo.rul的脚本文件,脚本如下:
- prototype SdComputerInfoDialog(string);
- #define RES_DIALOG_ID 12011 // ID of custom dialog
- #define RES_PBUT_NEXT 1 // ID of Next button
- #define RES_PBUT_CANCEL 1310 // ID of Cancel button
- #define RES_PBUT_BACK1308 // ID of Back button
- #define RES_EDITIP 1302 // ID of edit box
- #define RES_EDITUSER 1304
- #define RES_EDITPWD 1306
- #define RES_EDITPORT 1312
- function SdComputerInfoDialog(szTitle)
- STRING szDialogName, svName, svCompany;
- NUMBER nResult, nCmdValue;
- BOOL bDone;
- HWND hwndDlg;
- STRING szComputerIP, szFTPUser, szFTPPwd, szFTPPort;
- number nSize;
- begin
- szDialogName = "SdComputerInfo";
- nResult = EzDefineDialog (szDialogName, "", "", RES_DIALOG_ID);
- if (nResult < 0) then
- // Report an error; then terminate.
- MessageBox ("Error in defining dialog", SEVERE);
- abort;
- endif;
- bDone = FALSE;
- // Loop until done.
- repeat
- // Display the dialog and return the next dialog event.
- nCmdValue = WaitOnDialog (szDialogName);
- // Respond to the event.
- switch (nCmdValue)
- case DLG_CLOSE:
- // The user clicked the window's Close button.
- Do (EXIT);
- case DLG_ERR:
- MessageBox ("Unable to display dialog. Setup canceled.", SEVERE);
- abort;
- case DLG_INIT:
- hwndDlg = CmdGetHwndDlg( szDialogName );
- SdGeneralInit( szDialogName, hwndDlg, 0, szSdProduct );
- SdSetDlgTitle(szDialogName, hwndDlg, szTitle);
- nSize=MAX_PATH;
- MsiGetProperty( ISMSI_HANDLE, "LOCALHOST", szComputerIP, nSize );
- nSize=MAX_PATH;
- MsiGetProperty( ISMSI_HANDLE, "LOGINUSER", szFTPUser, nSize );
- nSize=MAX_PATH;
- MsiGetProperty( ISMSI_HANDLE, "LOGINPWD", szFTPPwd, nSize );
- nSize=MAX_PATH;
- MsiGetProperty( ISMSI_HANDLE, "FTPPORT", szFTPPort, nSize );
- CtrlSetText(szDialogName, RES_EDITIP, szComputerIP);
- CtrlSetText(szDialogName, RES_EDITUSER, szFTPUser);
- CtrlSetText(szDialogName, RES_EDITPWD, szFTPPwd);
- CtrlSetText(szDialogName, RES_EDITPORT, szFTPPort);
- case RES_PBUT_CANCEL:
- Do (EXIT);
- case RES_PBUT_BACK:
- bDone = TRUE;
- case RES_PBUT_NEXT:
- CtrlGetText (szDialogName, RES_EDITIP, szComputerIP);
- CtrlGetText (szDialogName, RES_EDITUSER, szFTPUser);
- CtrlGetText (szDialogName, RES_EDITPWD, szFTPPwd);
- CtrlGetText (szDialogName, RES_EDITPORT, szFTPPort);
- MsiSetProperty(ISMSI_HANDLE,"LOCALHOST", szComputerIP);
- MsiSetProperty(ISMSI_HANDLE,"LOGINUSER", szFTPUser);
- MsiSetProperty(ISMSI_HANDLE,"LOGINPWD", szFTPPwd);
- MsiSetProperty(ISMSI_HANDLE,"FTPPORT", szFTPPort);
- bDone = TRUE;
- endswitch;
- until bDone;
- // Close the dialog.
- EndDialog (szDialogName);
- // Remove the dialog from memory.
- ReleaseDialog (szDialogName);
- // If dialog is closed with Next button, display name and company.
-
- if nCmdValue = RES_PBUT_NEXT then
- return NEXT;
- else
- return BACK;
- endif;
- end;
复制代码
7.在OnFirstUIBefore事件中添加
- Dlg_ComputerInfo:
- szTitle = "设置服务器信息";
- nResult = SdComputerInfoDialog(szTitle);
- if (nResult = BACK) goto Dlg_UserInfo;
复制代码
8. 在XML File Changes节中添加记录信息,这里不再详述。
|