1. 程式人生 > >InstallShield使用——幾個技術問題介紹

InstallShield使用——幾個技術問題介紹

InstallShield使用——幾個技術問題介紹

1幾個技術問題介紹

1.1資料庫設定

在安裝程式中設定資料庫,有兩種方法:一種採用命令列附加資料庫檔案,一種是通過SQL Script指令碼建立資料庫,對於編寫SQL Script過於複雜,或建立資料庫時間過長時建議採用第一種方法。

1.1.1命令列附加資料庫

1.將資料庫檔案(a_data.mdfa_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.2SQL 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 ScriptsText Replacement頁面新增兩個替換引數,如下圖所示:

1.2InstallScirpt呼叫動態執行庫中的函式

安裝過程中有些設定是InstallShield無法做到的,需要其他的程式設計軟體實現,其他的程式設計軟體可以編寫成可執行的應用程式(EXE檔案),通過LaunchAppLaunchAppAndWait呼叫,也可以編寫成動態執行庫(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.1Basic MSI Project工程專案

1.建立自定義窗體,可參考標準窗體的各種設定,主要是窗體Behavior的設定,下面以一個例子說明建立過程;

2.建立一個記錄登入伺服器的資訊的自定義窗體,該窗體需要錄入伺服器的IP地址、使用者名稱及口令,將錄入資訊記錄到XML檔案中;

3.如下圖所示,在User InterfaceDialogsAll Dialogs點選右鍵,選擇New Dialgo選單,進入自定義窗體嚮導;

4.選擇Blank Dialog建立一個空白窗體,重新命名NewDialog1,如ServerLogin

5.如下圖所示選擇ServerLogin下的Chinse(Simplified)節,可設計此窗體;

6.新增三個Text Area,分別將Text屬性更改為伺服器IP:、使用者名稱:及口令:,新增三個Edit Field,分別錄入Property Name(屬性名稱)MY_SERVER_IPMY_SERVER_USERMY_SERVER_PWD 將口令的錄入框的Password屬性的值更改為True,新增三個Push Button,分別是上一步、下一步及取消,如下圖所示:

7.如果想將此窗體插入CustomerInformation窗體與SetupType之間,可選擇CustomerInformationBehaviorNext按鈕,如下圖所示,將EventNewDialogArgument更改為ServerLogin窗體;

8.選擇ServerLoginBehaviorNext按鈕 ,新增一個NewDialog事件,將Argument更改為SetupType窗體,Condition更改為1,同理在上一步按鈕中新增返回CustomerInformation窗體的事件,在取消按鈕中新增EventSpawinDialogArgumentCancelSetupCondiiton1,如下圖所示:

9.可以在Behavior and Logic中的Custom Actions and Sequences中可以看出窗體的執行順序,如下圖所示:

10.XML File Changes節中新增記錄資訊,這裡不再詳述。

1.3.2InstallScript MIS Project工程專案

1.建立自定義窗體需要注意在InstallScript中如何呼叫自定義窗體,並將窗體的屬性複製公共屬性,下面以一個例子說明呼叫;

2.建立一個記錄登入伺服器FTP的資訊的自定義窗體,該窗體需要錄入伺服器的IP地址、FTP埠、FTP使用者名稱及口令,將錄入資訊記錄到XML檔案中;

3.User InterfaceDialogsAll Dialogs點選右鍵,選擇New Dialgo選單,進入自定義窗體嚮導,選擇Blank Dialog建立一個空白窗體,重新命名NewDialog1,如SdComputerInfo,編輯窗體如下圖所示:

4.Direct EditorDialog中查出該窗體的ID,我建立的這個自定義窗體的ID12011,在Direct EditorControl中查出各控制元件的ID

5.Property Manager中新建四個屬性LOCALHOSTLOGINUSERLOGINPWDFTPPORT

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_BACK      1308   // 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節中新增記錄資訊,這裡不再詳述。