一個完整的安裝程序實例—艾澤拉斯之海洋女神出品(三) --高級設置一

第二部分: 腳本編程


在開始進行編程前,我們先明確一下我們要用編程來彌補前面設置的哪些功能的不足

1. 顯示軟件許可協議

2. 判斷是否安裝了本軟件所需要的先決軟件JKD1.6.0_04,如無,則啓動外部安裝程序進行安裝(同樣原理可以用來判斷是否安裝了其他軟件,只要該軟件在註冊     表中有鍵值)

3. 用戶的輸入信息、所選安裝路徑、所選安裝組件將顯示在安裝界面上(Installshield雖然自帶了此界面,但是默認是顯示爲空的,需要寫腳本來顯示信息)

4. 根據用戶選擇的組件,從外部文件夾拷貝相應的文件到安裝目標路徑的文件夾中

5. 根據從外部拷貝進來的文件,創建快捷方式(這裏主要是拷貝文檔,並在開始菜單中創建快捷方式)

6. 在安裝結束時,顯示readme.txt文件

7. 在安裝結束後,啓動指定的程序

8. 完美卸載

腳本編程這部分都將在Installer Designer這個界面進行。後面不再贅述。

Installshield大小寫敏感,因此請嚴格按照示例上所寫的大小寫規則來書寫。例:字符串變量STRING和string都支持,但是String不支持。

1. 顯示軟件許可協議

1. 添加許可協議文本

在左邊導航樹上找到Behavior and Logic | Support Files/Billboards選項。這個選項允許用戶添加一些在安裝過程中需要用到的文件。

clip_image002

中間的導航欄會顯示對應的選項

clip_image004

在Support Files分支下,會顯示一個Language Independent和所有你所選擇的語言類型。 Language Independent意爲,如果你在這裏分支下做了設置,那麼無論選擇用何種語言安裝,這個設置都會生效;而各個語言類型意爲,如果你在某語言下做了設置,那麼這個設置只有在選擇了用這種語言安裝的時候纔會生效。

點擊Language Independent,這次我們將在這個分支下進行試驗。

clip_image006

在右邊的Files欄中右鍵點擊,在彈出菜單上選擇Insert Files選項。

clip_image008

選擇事先撰寫好的許可協議的文本文件,插入到Files欄中。

許可協議允許兩種文本格式:txt和rtf格式,此處我們採用 txt格式。

2. 然後切換到Behavior and Logic | InstallScript選項,

clip_image010

3. 中間的導航欄Files下有一個默認的Rul文件Setup.Rul,我們這個工程的全部installscript代碼都將寫在這個默認文件裏

clip_image012

4. 點擊選中Setup.Rul節點,右邊會顯示該文件的可編程面板。

5. 許可協議應該在一開始運行安裝程序的時候就顯示,也就是在拷貝數據前。請在第一個下拉框中選擇Before Move Data選項,然後在第二個下拉框中選擇OnBegin選項(不要因爲默認顯示的是這兩個選項,而不做這個打開下拉列表進行選擇的動作,否則軟件檢測不到你選擇了選項,無法自動添加代碼),則編程界面上會自動添加一些代碼如下圖所示。當然,如果你手動敲代碼上去也是可以的。

clip_image014

6. 我們將在function OnBegin()的函數體裏面寫代碼來顯示剛纔添加的許可協議文本的內容,直接把下面的代碼拷貝到OnBegin()函數的begin和end;之間就可以了

Disable (BACKBUTTON);

if(!MAINTENANCE)then

SdLicense2 ("License ", "", "", SUPPORTDIR ^ "2.txt", FALSE);

endif;.

7. 代碼解釋

************************************************************************

Disable (BACKBUTTON);

將“上一步”按鍵設置爲不可用。安裝程序在一開始的時候會有一個默認的開始界面,第二步才顯示許可協議,一般來說沒必要回退回去看這個什麼都沒有的開始界面,因此將回退按鍵設置爲不可用

************************************************************************

if(!MAINTENANCE)then

endif;

這一個條件用來判斷安裝程序處於何種狀態,安裝、修復、重新安裝或卸載狀態,後三者都屬於MAINTENANCE狀態,因此判斷只有在正常安裝的狀態才顯示許可協議

************************************************************************

SdLicense2 ("License ", "", "", SUPPORTDIR ^ "2.txt", FALSE);

這個函數用於在界面上顯示所用的許可協議。Help裏對該函數的構造函數如下

SdLicense2 ( szTitle, szOpt1, szOpt2, szLicenseFile, bLicenseAccepted );

參數一:szTitle,顯示在界面左上角的標題,如果填寫空字符串””,則顯示爲默認值”License Agreement”。

參數二:szOpt1,我們常見許可協議界面上會有兩個選項,一個是“同意”,一個是“不同意”,szOpt1和szOpt2就是這兩個選項,如果填寫空字符串,則會顯示爲默認值"I accept the terms of the license agreement"和"I do not accept the terms of the license agreement"。

參數三:szOpt2,見參數二的說明

參數四:szLicenseFile,指定需要顯示的文檔,包含路徑和帶擴展名的文檔名。我們剛纔把許可協議文本放在supportfile選項下了,這個路徑在Installshield裏有專門的靜態變量來指明,即SUPPORTDIR,然後再添加上帶擴展名的文檔名,這裏是2.txt。靜態變量路徑和引號引起來的路徑之間用^符號來連接。

參數四:bLicenseAccepted,布爾型變量,TRUE狀態,則在許可協議界面上默認選中的是那個“同意”的選項;不過好像一般更常見的是默認選中爲“不同意”的選項,因此這裏可以填入FALSE。

clip_image016

這是許可協議的界面。當用戶選擇了I accept the terms of the license agreement這個選項後,Next按鍵可用,安裝程序可以繼續。(請忽略這裏顯示的許可協議內容…網上有很多軟件許可協議的範本供下載...)

小結:至此,許可協議就添加完畢,在安裝執行的時候,用戶就可以看到許可協議顯示在界面上,並且只有選擇了“同意”選項後,安裝程序纔會往下執行。

顯示許可協議的函數一共有三個SdLicense,SdLicenseRtf和SdLicense2,參數略有不同,顯示的界面也略有不同,用戶可以根據喜好來選擇。目前我常用的就是SdLicense2這個函數,顯示的界面符合大多數目前流行的安裝界面的習慣。

2. 判斷是否安裝了本軟件所需要的先決軟件或運行環境

1. 代碼還是在OnBegin()函數體內實現,直接把下面的代碼拷貝到OnBegin()函數的begin和end;之間就可以了

RegDBSetDefaultRoot(HKEY_LOCAL_MACHINE);

if (RegDBKeyExist ("SOFTWARE//JavaSoft//Java Development Kit//1.6.0_04") < 0) then

LaunchAppAndWait (SRCDISK^"jdk//jdk-6u4-windows-i586-p.exe","", LAAW_OPTION_WAIT);

endif;

2. 代碼解釋

************************************************************************

RegDBSetDefaultRoot(HKEY_LOCAL_MACHINE);

設置一下默認的註冊表鍵值根節點爲HKEY_LOCAL_MACHINE。

打開註冊表可以看到“我的電腦”下的根節點有HKEY_CLASSES_ROOT, HKEY_CURRENT_USER,HKEY_LOCAL_MACHINE等。我們這次要尋找的JDK軟件的註冊表鍵值在HKEY_LOCAL_MACHINE下,因此要把根鍵設置爲HKEY_LOCAL_MACHINE。

表告訴我你不知道怎麼看註冊表,開始-〉運行-〉輸入命令regedit

***********************************************************************

RegDBKeyExist ("SOFTWARE//JavaSoft//Java Development Kit//1.6.0_04") < 0)

判斷是否存在鍵值SOFTWARE//JavaSoft//Java Development Kit//1.6.0_04,這個是JDK1.6.0_04安裝時向註冊表寫入的值;

RegDBKeyExist( szSubKey );如果存在鍵值則返回1,否則返回小於0的隨機數字。

***********************************************************************

LaunchAppAndWait (SRCDISK^"jdk//jdk-6u4-windows-i586-p.exe","", LAAW_OPTION_WAIT);

當上面判斷了沒有安裝JDK1.6.0_04這個軟件時,則啓動光盤裏jdk文件夾下的jdk-6u4-windows-i586-p.exe安裝程序來安裝。

這個函數在help裏是這樣敘述的:

LaunchAppAndWait ( szProgram, szCmdLine, nOptions );

參數一:szProgram,即要啓動的程序。這裏我們寫入的參數是SRCDISK^"jdk//jdk-6u4-windows-i586-p.exe", SRCDISK指源盤,安裝程序所在的盤,光盤和硬盤都可以。"jdk//jdk-6u4-windows-i586-p.exe"源盤下jdk文件夾下的jdk-6u4-windows-i586-p.exe安裝程序。

參數二:szCmdLine,如果要啓動的程序需要從命令行讀入參數來啓動,那麼在這裏寫入對應的參數值;我們這裏不需要,因此輸入空字符串””。

參數三:nOptions,靜態變量,不同的靜態變量會得到不同的執行結果,比如無等待安裝,靜默安裝,鼠標外形改變等等。詳情請參閱Installshield自帶的Help。這裏我們用LAAW_OPTION_WAIT,即當JDK安裝結束後(無論是正常安裝了,還是用戶點擊取消了安裝),安裝程序才往下繼續。

clip_image018

這裏可以看到,當點擊了同意許可協議的時候,安裝程序會自動檢測是否安裝了JDK,如果沒有安裝,則彈出安裝界面。

這裏在函數體裏面,沒有對找不到JDK安裝程序,以及安裝出錯等情況做判斷。如果用戶有需要,可以添加一個消息框,提示在找不到安裝程序或者安裝出錯的情況下,用戶可以手動地安裝需要的軟件。代碼可以改寫爲

RegDBSetDefaultRoot(HKEY_LOCAL_MACHINE);

if (RegDBKeyExist ("SOFTWARE//JavaSoft//Java Development Kit//1.6.0_04") < 0) then

if(LaunchAppAndWait (SRCDISK^"jdk//jdk-6u4-windows-i586-p.exe","", LAAW_OPTION_WAIT)<0)then

MessageBox ("You haven't installed JDK 1.6.0_04 yet! ", INFORMATION);

endif;

endif;

小結:至此,判斷運行所需軟件的功能結束,用戶可以自己試驗一下判斷多個軟件。用法就是重複上述代碼功能,仍在OnBegin()函數體內執行。

3. 用戶的輸入信息、所選安裝路徑、所選安裝組件顯示在安裝界面上

Installshield是自帶這個界面的,在安裝過程中用戶可以看到這個界面,但是這個界面上的信息是空的,這一點讓人很是疑惑,懷疑是Installshield的bug。因此我們不得不手動地實現這個功能。

1. 這個功能需要在OnFirstUIBefore()函數體中實現,選擇Before Move Data | OnFirstUIBefore選項

clip_image020

2. 選擇了這個選項後,軟件會自動在編程界面生成大量代碼,如圖所示,這裏的每一個Dlg_SdXXXX都對應着一個界面,例如Dlg_SdWelcome就是對應着最初開始的歡迎界面。如果開發人員對這些很熟悉,可以在這裏對每一個界面編程設置。

clip_image022

3. 找到Dlg_SdStartCopy這個界面選項,我們將在這裏對已有的代碼進行改動,使之顯示用戶輸入的用戶信息、所選安裝路徑和組件等信息

clip_image024

4. 首先定義所需變量。

在begin前定義6個feature的名字和兩個NUMBER類型的變量,即藍色字串。之前在第一部分我們定義了6個可用的feature,這裏就要對這6個feature進行一些判斷。

在begin字樣後對這6個feature賦值,所賦的值就是我們在第一部分定義的feature的名字(Name, not Display Name)。

//---------------------------------------------------------------------------

function OnFirstUIBefore()

NUMBER nResult, nSetupType, nvSize, nUser;

STRING szTitle, szMsg, szQuestion, svName, svCompany, szFile;

STRING szLicenseFile;

LIST list, listStartCopy;

BOOL bCustom;

STRING szFeatureName1;

STRING szFeatureName2;

STRING szFeatureName3;

STRING szFeatureName4;

STRING szFeatureName5;

STRING szFeatureName6;

NUMBER bvOpt1,bvOpt2;

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));

szFeatureName1 ="Server";

szFeatureName2 ="Client";

szFeatureName3 ="Watch_Portion";

szFeatureName4 ="Log_Portion";

szFeatureName5 ="Report_Portion";

szFeatureName6 ="Document";

5. 在Dlg_SdStartCopy的listStartCopy = ListCreate( STRINGLIST ); 和ListDestroy(listStartCopy);之間加入如下代碼。

ListAddString(listStartCopy,"Customer Information:",AFTER);

ListAddString(listStartCopy,"User Name: " + svName,AFTER);

ListAddString(listStartCopy,"Company Name: " + svCompany,AFTER);

ListAddString(listStartCopy,"Destination Location: " + INSTALLDIR,AFTER);

switch (nSetupType)

case TYPICAL : ListAddString(listStartCopy,"Setup Type: Typical",AFTER);

case COMPACT: ListAddString(listStartCopy,"Setup Type: Compact",AFTER);

case CUSTOM: ListAddString(listStartCopy,"Setup Type: Custom",AFTER);

endswitch;

ListAddString(listStartCopy," ",AFTER);

ListAddString(listStartCopy,"The Selected Feature:",AFTER);

if (FeatureIsItemSelected(MEDIA, szFeatureName1)=1) then

ListAddString(listStartCopy," "+szFeatureName1,AFTER);

endif;

if (FeatureIsItemSelected(MEDIA, szFeatureName2)=1) then

ListAddString(listStartCopy," "+szFeatureName2,AFTER);

endif;

if (FeatureIsItemSelected(MEDIA, szFeatureName3)=1) then

ListAddString(listStartCopy," "+szFeatureName3,AFTER);

endif;

if (FeatureIsItemSelected(MEDIA, szFeatureName4)=1) then

ListAddString(listStartCopy," "+szFeatureName4,AFTER);

endif;

if (FeatureIsItemSelected(MEDIA, szFeatureName5)=1) then

ListAddString(listStartCopy," "+szFeatureName5,AFTER);

endif;

if (FeatureIsItemSelected(MEDIA, szFeatureName6)=1) then

ListAddString(listStartCopy," "+szFeatureName6,AFTER);

endif;

6. 代碼解釋

*************************************************************

ListAddString(listStartCopy,"XXXXXX",AFTER);

把要顯示的信息添加到list裏去,這個list的內容稍後會添加到界面上進行顯示。

Help裏對這個函數是這樣描述的:ListAddString ( listID, szString, nPlacementFlag );

參數一:listID,需要用戶事先創建一個list,這裏我們看到listStartCopy = ListCreate( STRINGLIST );這句話,即創建了一個叫listStartCopy的list

參數二:szString,要添加的字符串

參數三:nPlacementFlag,如果設置爲AFTER,則順序添加;如果爲BEFORE,則逆序添加,即新添加的內容會放在前面顯示。

*************************************************************

switch (nSetupType)

case TYPICAL : ListAddString(listStartCopy,"Setup Type: Typical",AFTER);

case COMPACT: ListAddString(listStartCopy,"Setup Type: Compact",AFTER);

case CUSTOM: ListAddString(listStartCopy,"Setup Type: Custom",AFTER);

endswitch;

這是根據用戶選擇的安裝類型來顯示安裝類型信息。安裝類型分三種:TYPICAL,COMPACT和CUSTOM。

*************************************************************

if (FeatureIsItemSelected(MEDIA, szFeatureName1)=1) then

ListAddString(listStartCopy," "+szFeatureName1,AFTER);

endif;

這裏的FeatureIsItemSelected(MEDIA, szFeatureName1)=1是一個很重要的函數,將會在本安裝程序內反覆出現多次。這個函數用於判斷用戶是否選擇了某feature。Help裏對這個函數是這樣描述的:FeatureIsItemSelected ( szFeatureSource, szFeature );

參數一:szFeatureSource,大意好像是feature的來源,具體不是很明白到底指什麼,反正help自帶的例子裏寫的MEDIA照抄沒有錯。

參數二:szFeatureName1,就是 feature的名字了

如果用戶選擇了這個feature,返回值就爲1,往list裏添加一個關於該feature的相關信息即可。

如此反覆,判斷所有的feature是否被選擇,如被選擇則添加一個相關信息即可。

clip_image026

這個就是顯示了用戶信息,安裝路徑和安裝組件的信息。如果沒有添加上述代碼,這個界面默認是顯示的,但是信息欄裏是空白的。

順便說一句,以前在製作這個安裝程序的時候,因爲這塊顯示是空白的,那時候對編程也是一竅不通的,情急之下,筆者把這個顯示設置的框框設置了不可見。設置方法如下:

找到User Interface | Dialogs

clip_image028

在中間的導航樹上找到SdStartCopy這個選項

clip_image030

這裏我們使用的是英文界面,因此點擊選中English選項

clip_image032

選中這個界面上的將會顯示用戶信息的框,把右邊的Visible選項設置爲False即可

小結:在Dlg_SdStartCopy界面裏,用戶還可以設置左上角顯示的標題和消息,szTitle = ""; szMsg = "";這兩行代碼如果賦值爲空,則顯示如圖所示的默認信息,用戶可以賦值成自己想要顯示的信息。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章