前言
Installshield可以說是最好的做安裝程式的商業軟體之一,不過因為功能的太過於強大,以至於上手和精通都不是容易的事情,之前都是用Installshield的Project Assistant對付過去的,這次做這個安裝程式,為了實現一些功能,必須寫代碼,國內外現成的資料很少,而且很多都語焉不詳,自己反覆啃了多次,對比Installshiel內建的help,才明白資料所表達的意思。這個安裝程式雖然比較簡陋,在行家眼裡可能是小菜一碟,但是也花了筆者一個星期的時間,閱讀了很多資料,啃了好幾天英文help,整合了很多先驅者的經驗,也費了自己不少心血做成的,對每一段代碼的用處、每一個用到的函數都進行了詳細的說明,因此轉載時請務必保留轉載出處和由艾澤拉斯之海洋女神出品的字樣;如需刊登,請與作者聯絡。
在此要感謝吞硬幣的小豬,天下曉明,餘滿青,海洋C++樂園(此海洋不是彼海洋)等大蝦在互連網上的無私奉獻,他們的貼子和部落格給了我很大啟示。
因為本人是做java出身的,因此對這種類C++語言還是第一次接觸,有理解不當之處,請朋友們指正。歡迎Email至little_fairycat@126.com
本文
需求:公司做了一個軟體產品,
1. 該軟體運行需要JDK環境(不是JRE,因為該軟體要向windows註冊一個服務,用到了JavaService,JDK才支援這個功能;不過這裡側重於判斷是否安裝了某軟體是否安裝,而不是糾纏於該裝JDK還是該裝JRE);
2. 由於是Server-Client形式的,需要允許使用者選擇安裝組件,比如A機只裝Server端,B機只裝Client端;
3. 文檔不打包在安裝程式裡,直接存放在光碟片檔案夾下方便使用者查看,同時允許使用者指定是否安裝文檔到電腦上(為什麼這樣做,後面說明詳細原因);
4. 該軟體會以授權形式發放給使用者,不同的使用者,軟體本身可能相同,而不同的只是授權檔案和一些配置,因此希望授權檔案和設定檔不打包在安裝程式裡,而直接存放在光碟片裡,以減少可能的重複打包安裝程式的勞動;
5. 在安裝完畢後,希望能自啟動程式(因為該軟體需要在安裝完畢後啟動一個程式,該程式實現向Windows註冊服務的功能,該程式最好由安裝程式啟動,而不是由客戶手動啟動)。
6. 希望有反安裝程式
本文提到的“外部”指不打包在安裝程式裡的,與安裝程式一起存放在光碟片裡的一些檔案夾,這些檔案夾包含了安裝中所需要的檔案,同時也可能有其他用途,因此不適合直接壓縮打包在安裝程式裡。
該執行個體實現了如下功能:
1. 顯示軟體許可協議
2. 判斷是否安裝了本軟體所需要的先決軟體JKD1.6.0_04,如無,則啟動外部安裝程式進行安裝(同樣原理可以用來判斷是否安裝了其他軟體,只要該軟體在註冊表中有索引值)
3. 安裝允許使用者選擇需要安裝的組件
4. 使用者的輸入資訊、所選安裝路徑、所選安裝組件將顯示在安裝介面上(Installshield雖然內建了此介面,但是預設是顯示為空白的,需要寫指令碼來顯示資訊)
5. 根據使用者選擇的組件,在開始菜單顯示程式的捷徑(同樣適用於案頭捷徑,後面做詳細說明)
6. 根據使用者選擇的組件,從外部檔案夾拷貝相應的檔案到安裝目標路徑的檔案夾中
7. 根據從外部拷貝進來的檔案,建立捷徑(這裡主要是拷貝文檔,並在開始菜單中建立捷徑)
8. 在安裝結束時,顯示readme.txt檔案
9. 在安裝結束後,啟動指定的程式
10. 完美卸載
筆者所用的環境為Installshield 12 Premier Edition,Windows XP with SP2, 該環境下建立的工程可以直接使用在Installshield 2008 Premier Edition下,Installshield 2008在開啟Installshield 12所建的工程時會提示你是否需要進行Upgrade,確認即可,軟體會自動為你進行升級,很方便。
下面我們一步一步來建立一個基本的工程,並且使用指令碼來完善和豐富所需功能
第一部分:基本設定
1. 開啟Installshield 12 Premier Edition,建立一個Installscript MSI Project,這種被稱之為半指令碼程式,因為兼具Basic Project基本類型和Installscript Project全指令碼類型兩者的優點,我比較喜歡用。像我這樣需求的,既要用到Wizard的便利,又想寫一點指令碼來實現一點自訂動作的,就比較適合用這種類型啦。
選擇類型為Windows Installer | InstallScript MSI Projcet,輸入工程名,指定工程所在的檔案夾。
2. 介面會切換到Project Assistant,我們先從這裡開始把工程的基本組件和基本檔案建立好。
3. 在Project Assistant介面的底部,會有一個引導動作條,在建立該工程的基本結構和檔案時,我們都將在此介面進行操作,下文都將以“引導條”來指代這個引導動作條。
4. 點擊引導條上的Application Information
這裡輸入:
公司名,公司名將會出現在Setup.exe的註解中
軟體名,將會出現在安裝過程的左上方標題列上
版本號碼,沒看到在哪,不過自己比較方便地知道自己在編譯哪個版本的軟體
公司網址,沒看到在哪,而且如果該公司沒有網址呢。而且這裡有點bug,好像預設的值總是會報一個String_ID1為空白的錯誤,自己輸入一個網址就不會報錯。
是否在你建立了更新時自動通知終端使用者,沒用過,我都選了No。
選擇一個表徵圖,這個表徵圖會出現在“添加或刪除程式”裡,我一般用預設的,當然你可以替換成自己想要的表徵圖。
5. 點擊引導條上的Installation Requirement
這裡選擇對作業系統和一些軟體的需求。根據自己需要來選擇是否要求作業系統的版本,已經是否要求安裝了某些軟體。
6. 點擊引導條上的Installation Architecture
這是個十分有用的設定,對於本文所用的分布式軟體來說非常合適,分布式軟體的每個組件可以設定為一個Feature,使用者可以自由選擇安裝某些功能。
將選項Do you want to customize your Installation選擇為Yes。
點擊選中根節點Installation Architecture,點擊New建立新的Feature,可以為每個Feature指定新名稱。
還可以在Feature下建立子Feature,比如如果文檔Feature下包括軟體本身文檔,和軟體所需的運行環境的文檔,那麼可以建立兩個子Feature,分別包含兩種文檔,使用者在安裝時就可以選擇安裝部分或者全部文檔了。這裡我們沒有用到子Feature,用途和普通Feature一樣。
這裡,建立好所有Feature後,我們將切換到Installation Designer做一個設定
找到Installation Designer頁面上左邊導航樹Organization | Features分支,你會看到這裡Features都顯示為原始的名稱,而非我們改過的名字,因為Feature有Name和Display Name兩種名稱,我們剛才改的不過是Display Name,為了便於查看和使用,我們在這裡把Name也改一下
注意Name不可以有空格,可以使用底線
繼續切換回Project Assistant
7. 點擊引導條上的Application Files
我們將在這裡對安裝路徑進行微調,並且為每個Feature指定需要安裝的檔案
這裡我不想使用Program Files | Company Name | Product Name這個路徑,我想使用Program Files | Product Name,我直接點擊選中My Product Name[INSTALLDIR]拖動到ProgramFileFolder下,還可以直接將My Product Name 改成自己想要的檔案夾名字
接下來,為每個Feature指定要安裝的檔案。
開啟這個下拉式清單,所有的Feature都在這裡,按順序來給每一個Feature建立檔案夾,並且匯入所需的檔案。
選擇第一個Feature, 即Server,點擊My Product Name[INSTALLDIR]節點,右鍵點擊,在菜單上選擇New Folder來建立一個檔案夾。
建立一個Server檔案夾,這個檔案夾將用來存放該組件需要的一些檔案。
再在Server檔案夾下建立一個icon檔案夾,存放該組件所用的表徵圖。
然後為該Feature添加安裝時該Feature要安裝的檔案。
這裡我們建立的icon檔案夾是用來存放這個feature在後面要建立捷徑時使用的表徵圖的。為這個icon檔案夾添加相應的表徵圖檔案,並且記住表徵圖檔案的來源檔案夾,後面設定捷徑的時候要用。
點擊選中要添加檔案的檔案夾,然後點擊右下角的Add Files,然後添加檔案
接下來我們為Feature添加檔案夾,如果這個檔案夾中的全部檔案都為這個Feature所需。添加檔案夾的好處在於只要檔案夾位置和名稱不變,那麼檔案夾裡面的檔案都是動態載入的,有多少載入多少,不用考慮檔案名稱的改動帶來的影響。
點擊選中要添加檔案夾的檔案夾,然後點擊右下角的Add Folders,然後添加檔案夾。
選中檔案夾,點擊確定。
會詢問你是否要使用動態檔案連結,我都選擇確定,好處就在於我剛才上面所述。
顯示了源檔案夾,如果這個檔案夾下有子檔案夾,並且也需要一併添加進來的話,務必鉤選Include subfolders選項。
這裡還允許做一些簡單設定來包含或者排除一些特定檔案,支援萬用字元。
點擊OK確定加入檔案夾。
如法炮製為每個Feature建立檔案夾,並且添加檔案,最後效果如圖所示
Document這個Feature,除了檔案所用的表徵圖外,什麼都不要添加,後面我們將用安裝時即時拷貝的方式來拷貝文檔進來。
8. 接下來我們為可執行檔建立捷徑。
點擊引導條上的Application Shortcuts
點擊New建立一個捷徑
選擇一個要建立捷徑的Feature。
如果要建立捷徑的程式為非.exe形式,請把Files Of選擇選為All Files(*.*)格式。
我們的程式安裝目標路徑設定在Program Files下,因此雙擊[ProgramFilesFolder]開啟,層層點擊進入。
我們這裡要為client.bat建立一個捷徑,因為這個是啟動用的批次檔。
Installshield可以自動監測到.exe檔案的存在,自動產生捷徑,使用者只需要做一些適當修改即可。
建立的捷徑將出現在這裡,名字不好聽,樣子也不好看,我們將為它改一個名字,並且換一個表徵圖。
選中捷徑,點擊Rename,並且為這個捷徑改一個適當的名字。
注意右邊的幾個選項。
Create shortcut in Start Menu,將在開始菜單裡建立一個捷徑。
Create shortcut on Desktop,將在案頭上建立一個捷徑。
Use alternate shortcut Icon,替換捷徑的表徵圖
Associate a file extension with the shortcut’s target,沒用過,不知道什麼意思。
我們在這裡將只建立開始菜單的捷徑,因此鉤選第一項。
鉤選第三項,並且點擊Browse來瀏覽表徵圖。
請回想剛才在為Feature添加檔案的時候,每個feature都添加了對應的icon。這裡,請把瀏覽的檔案夾設定為剛才添加icons所用的檔案夾,通俗的說,就是你剛才從哪兒添加一個表徵圖進feature的,現在還是從哪兒添加的這個表徵圖。
其實這一點我是一直很費解的,當初不知道要這麼選擇表徵圖,隨便從外面一個任意檔案夾裡添加了一個表徵圖,以至於打包後死活找不到表徵圖,後來經過實驗才知道這個被選中的表徵圖檔案要拷貝進來,打包進安裝檔案才可以。這一點上不能不提一下visual studio,這個工具做安裝程式雖然功能一般,但是思想還是不錯的,當它的組件指定拷貝了表徵圖檔案後,在建立捷徑時,捷徑使用的表徵圖是指向虛擬安裝目標路徑下的表徵圖檔案的,而不是指定到這個實實在在的源檔案夾。這一點差別就體現出了思想上的差異。
如法炮製為每個Feature指定捷徑,Document除外,因為我們在這個feature裡除了表徵圖檔案外什麼都沒有添加。
至此我們為每個可執行程式添加了開始菜單下的捷徑。
我們再切換去Installation Designer,找到System Configuration | Shortcuts。
看到捷徑在開始菜單中是以 公司名 | 軟體名 | 捷徑 這種形式存在的。事實上我是不喜歡這種形式了,想想點開一層還有一層,不如直接了當來得乾脆,因此做一些修改。
這裡我改成了如下設定
不要告訴我你不會改,直接拖動Test檔案夾往Program Menu(即開始菜單下的那個“所有程式”)下一塞即可,然後刪除掉多餘的Company Name檔案夾。
9. 可能剛才在Project Assistant介面有人已經注意到了左側邊欄上More Options下Create an uninstallation shortcut這個誘人的字樣了。
可是我要告訴你,如果你選擇了這種方式建立卸載捷徑的話,你會很沮喪地發現:
a) 似乎只有在安裝某個feature的時候這個卸載捷徑才會出現(當然,就是那個default feature,這種要命的feature形式決定了每個檔案或者捷徑都必須明確地歸屬到某個feature下),因此,當你的客戶只選擇了其他feature安裝時,這個卸載方式不會出現,而他必須去“添加或卸載程式”裡面去卸載
b) 如果你寫指令碼使得安裝時會拷貝一些外部檔案進來,那麼這些檔案在這種卸載方式下是刪除不掉的。(如果你確實想儲存這些檔案,你可以在指令碼裡設定它們屬性為permanent,這個屬性可以保證什麼卸載方式都不能刪除你的這些檔案)。
所以這裡我們忽視這個卸載捷徑的存在,而將在後面採用指令碼形式實現完美卸載。
10. 點擊引導條上的Application Registry
向註冊表寫鍵和索引值,由於本工程不需要,忽略之。有需要的朋友可以查閱相關資料,不難。
11. 點擊引導條上的Installation Location
這個是用來設定安裝包的語言的,選擇了多個語言後,使用者可以在安裝介面開始的時候選擇安裝時所用的語言;不過作為一個公司產品來說,這麼偷懶,客戶的印象是要打折扣的,所以還是選個單語言吧,該什麼語言的安裝包就什麼語言的安裝包,各歸各。
不過你又會沮喪地發現,如果要選擇一種其他語言作為Default Language,好像又報錯了。
這個問題當時折騰了我一個星期(當然那時候才接觸Installshield,還一竅不通),最後問了支援人員才得以解決。
切換去Installation Designer,找到Installation Information | General Information,看到String Tables下面是什麼。對,所有你選的語言都列出來了,選中你要的語言,右鍵,選擇Make Default,OK,再切換回Project Assistant去把所有不要的語言統統去掉鉤選即可。
看到此處,已經變成了English為預設語言了。
12. 點擊引導條上的Build Installation。
打包安裝盤的設定,本人從來不用這個選項,都用工具條上的Release Wizard。
至此,第一部分基本完成。如果是一些沒有特別要求的安裝包,這部分講解的內容足夠可以做一個基本的安裝包了
第二部分:指令碼編程
在開始進行編程前,我們先明確一下我們要用編程來彌補前面設定的哪些功能的不足
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選項。這個選項允許使用者添加一些在安裝過程中需要用到的檔案。
中間的導覽列會顯示對應的選項
在Support Files分支下,會顯示一個Language Independent和所有你所選擇的語言類型。 Language Independent意為,如果你在這裡分支下做了設定,那麼無論選擇用何種語言安裝,這個設定都會生效;而各個語言類型意為,如果你在某語言下做了設定,那麼這個設定只有在選擇了用這種語言安裝的時候才會生效。
點擊Language Independent,這次我們將在這個分支下進行實驗。
在右邊的Files欄中右鍵點擊,在快顯功能表上選擇Insert Files選項。
選擇事先撰寫好的許可協議的文字檔,插入到Files欄中。
許可協議允許兩種文字格式設定:txt和rtf格式,此處我們採用 txt格式。
2. 然後切換到Behavior and Logic | InstallScript選項,
3. 中間的導覽列Files下有一個預設的Rul檔案Setup.Rul,我們這個工程的全部installscript代碼都將寫在這個預設檔案裡
4. 點擊選中Setup.Rul節點,右邊會顯示該檔案的可程式化面板。
5. 許可協議應該在一開始運行安裝程式的時候就顯示,也就是在拷貝資料前。請在第一個下拉框中選擇Before Move Data選項,然後在第二個下拉框中選擇OnBegin選項(不要因為預設顯示的是這兩個選項,而不做這個開啟下拉式清單進行選擇的動作,否則軟體檢測不到你選擇了選項,無法自動添加代碼),則編程介面上會自動添加一些代碼如下圖所示。當然,如果你手動敲代碼上去也是可以的。
6. 我們將在function OnBegin()的函數體裡面寫代碼來顯示剛才添加的許可協議文本的內容,直接把下面的代碼拷貝到OnBegin()函數的begin和end;之間就可以了
Disable (BACKBUTTON);
if(!MAINTENANCE)then
SdLicense2 ("License ", "", "", SUPPORTDIR ^ "2.txt", FALSE);
endif;.
7. 代碼解釋