欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

探索InstallShield——制作一個(gè)完整的應(yīng)用程序安裝實(shí)例

  發(fā)布時(shí)間:2008-09-05 09:56:37   作者:佚名   我要評(píng)論
大家一定有過這樣的經(jīng)歷,每當(dāng)我們殫精竭慮為用戶開發(fā)完一個(gè)系統(tǒng)之后往往都是派一名技術(shù)員到用戶那里進(jìn)行應(yīng)用軟件的安裝,數(shù)據(jù)庫的配置,這些看似簡單的配置對(duì)一般用戶來說可不是件容易做的事。這不僅給那些喜歡力求完美的程序設(shè)計(jì)師帶來一點(diǎn)遺憾外,而且也使我們
大家一定有過這樣的經(jīng)歷,每當(dāng)我們殫精竭慮為用戶開發(fā)完一個(gè)系統(tǒng)之后往往都是派一名技術(shù)員到用戶那里進(jìn)行應(yīng)用軟件的安裝,數(shù)據(jù)庫的配置,這些看似簡單的配置對(duì)一般用戶來說可不是件容易做的事。這不僅給那些喜歡力求完美的程序設(shè)計(jì)師帶來一點(diǎn)遺憾外,而且也使我們設(shè)計(jì)出來的軟件缺少一種安全可靠感。如果我們在交給用戶軟件的時(shí)候能給他們一個(gè)象一些專業(yè)軟件的安裝程序,這不僅給用戶留下了一個(gè)良好的第一印象,同時(shí)也節(jié)省了開發(fā)維護(hù)成本。
要說起制作安裝程序的軟件有許多,像InstallShield,CreateInstall,Easy Install,EasySetup,SetupBuilder等等,可以舉出一大堆來。但其中最為著名的當(dāng)屬InstallShield。目前世界上絕大多數(shù)的商業(yè)軟件的安裝盤都是用她來完成,比如我們可能天天在使用的Norton AntiVirus 2000。
InstallShield之所以很流行也許是因?yàn)槌绦騿T可以在通過編寫腳本語言方便的進(jìn)行Windows應(yīng)用程序的注冊表修改、ODBC配置等復(fù)雜的操作,以及她本身提供了一些相當(dāng)智能化的功能。下面,就本人在實(shí)際開發(fā)中的一些所得和大家一起探討,文中如有任何不妥之處還請(qǐng)同行們給予指教。
在講述到數(shù)據(jù)庫配置的一系列問題是以目前最常用的ODBC接口為基礎(chǔ),文中用到的實(shí)例是在WIN98系統(tǒng)中,InstallShield用的是Professional 6.21下開發(fā)和調(diào)試的,其中的應(yīng)用程序?qū)嵗玫腜owerBuilder 7.0下開發(fā)的演示程序。
第一步:快速體驗(yàn)
首先,我們可以來快速體驗(yàn)一下用InstallShield制作的安裝程序是什么樣的。
當(dāng)然,我不可能詳細(xì)到怎樣建立一個(gè)項(xiàng)目之類的問題,有關(guān)這方面的內(nèi)容還請(qǐng)看InstallShield的入門教材。
第二步:;InstallShield初探
首先,用Project Wizard建立一個(gè)新的項(xiàng)目,取名Demo,同時(shí)在對(duì)話框中選擇所有的選項(xiàng),并且在語言選擇中選擇Chinese(PRC)和English,即簡體中文和英文支持。當(dāng)然你也可以選擇其它語言,為了便于討論我只選擇了Chinese(PRC)和English。
運(yùn)行一下試一試,一切都正常,只是一個(gè)空殼罷了,沒有任何東西。
好了,戰(zhàn)斗的號(hào)角已經(jīng)吹響了,讓我們集中精力個(gè)個(gè)殲滅。
一、 語言選擇

由于我們在生成項(xiàng)目的同時(shí)在語言選擇中選擇了Chinese(PRC)和English,因此,在圖01中的下拉列表框中會(huì)自動(dòng)出現(xiàn)中文,英文的選項(xiàng)。這一步由模板自動(dòng)完成,我們不要做任何事情。
二、 設(shè)置啟動(dòng)畫面

在我們生成項(xiàng)目的同時(shí),InstallShield會(huì)為我們?nèi)笔〉姆派弦粡垎?dòng)畫面。見圖16。

從該圖片上我們可以看出,一般情況下是放置一張能很好的代表你公司的圖片,同時(shí)上面很清楚地標(biāo)明你的應(yīng)用程序的名稱,版本,公司名稱,版權(quán)歸屬等基本信息。毫無疑問,我們必須用我們自己的圖片來替換它。替換的方法是,在Setup File面板中,打開Splast Screen,找到Language Independent,這時(shí)我們會(huì)發(fā)現(xiàn)在它右邊的列表中有一個(gè)文件Setup.bmp,它就是圖18的那一張,我們必須首先把它刪除,然后再插入我們想要的那一張,在列表中任何一個(gè)位置點(diǎn)擊鼠標(biāo)右鍵,選擇Insert Files,用一個(gè)BMP文件替換它就行了。注意,我們替換的圖片的文件名必須是Setup.bmp。
另外,順便提一下,在Splash Screen下除了Language Independent分支外,還有Chinese(PRC)和English分支,如果在它們中放置不同的Setup.bmp文件,那么系統(tǒng)會(huì)根據(jù)用戶在安裝前選擇了不同的語言而啟動(dòng)不同的背景,這樣可以有效地避免多國語言的煩惱。同樣,在設(shè)置法律聲明(許可協(xié)議)和自述文件的時(shí)候也是一樣的。
三、 開始安裝

這一步由系統(tǒng)自動(dòng)給出,我們不要做任何事情。但是我們可以在這里進(jìn)行軟件安裝前的準(zhǔn)備工作。比如,操作系統(tǒng)判斷,機(jī)器可用內(nèi)存容量的檢測等,這些往往被忽視。
當(dāng)我們用項(xiàng)目向?qū)傻男马?xiàng)目時(shí),InstallShield只為我們生成兩個(gè)事件,分別是OnFirstUIBefore和OnMoving,它們的意義是,
OnFirstUIBefore:在應(yīng)用程序第一次安裝時(shí)為了搜集用戶信息而彈出的對(duì)話框之前,應(yīng)用程序所響應(yīng)的事件。
OnMoving:該事件在當(dāng)所選擇的安裝組件正在安裝或反安裝時(shí)響應(yīng)。
顯然,準(zhǔn)備工作可以在事件OnFirstUIBefore中完成,但I(xiàn)nstallShield同時(shí)還為我們提供了事件OnBegin,該事件在是在Setup腳本中第一個(gè)被觸發(fā)。還記得圖片02,上面有個(gè)進(jìn)度條,顯示了“正準(zhǔn)備InstallShield(R)向?qū)?..”,當(dāng)該進(jìn)度條結(jié)束后就首先調(diào)用OnBegin,然后才是OnFirstUIBefore。因此,我們可以將一些前期的準(zhǔn)備工作放到這里來完成。下面是如何具體實(shí)現(xiàn)。
1、首先,如何添加OnBegin事件?
InstallShield將事件分成三類:全局事件,組件事件和雜項(xiàng)事件。其中,全局事件的添加最為方便,只要將當(dāng)前行光標(biāo)移到Serup腳本的最后,然后寫上
function OnBegin()
begin
... // 函數(shù)體
end;
就行了。
2、實(shí)現(xiàn)操作系統(tǒng)的識(shí)別
像其它編程工具一樣,InstallShield也為我們提供了一些系統(tǒng)變量,利用這些變量我們可以輕而易舉的得到一些像系統(tǒng)目錄,語言代碼,CUP類型等實(shí)用數(shù)據(jù)。
具體實(shí)現(xiàn)代碼如下:
/*****************程序代碼*******************/
Function OnBegin()
Begin
if ( !SYSINFO.bIntel) then
szMsg = "提示:該軟件只能運(yùn)行在Intel系列的處理器上!\n\n安裝程序?qū)⒔K止";
MessageBox(szMsg, SEVERE);
abort;
endif;
if (SYSINFO.WIN9X.bWinMe ||
SYSINFO.WINNT.bWinNT ||
SYSINFO.WINNT.bWinNT4 ||
SYSINFO.WINNT.bWin2000) then
szMsg = "提示:該軟件只能運(yùn)行在WIN9X系統(tǒng)上才能確保程序的正常工作!\n\n是否繼續(xù)安裝?";
if ( !AskYesNo (szMsg, NO)) then
abort;
endif;
endif;
end
/******************結(jié)束*********************/
相關(guān)變量:SYSINFO
存放本機(jī)的一些系統(tǒng)變量,如操作系統(tǒng),CUP類型等。有關(guān)系統(tǒng)變量的具體使用請(qǐng)參閱編程手冊。
相關(guān)函數(shù):AskYesNo
該函數(shù)彈出一消息窗口,用戶通過按是或非來回答該窗口顯示的問題。
3、實(shí)現(xiàn)內(nèi)存容量的檢測
在查閱了InstallShield系統(tǒng)變量后并沒有找到有關(guān)內(nèi)存容量方面的變量,因此只有通過調(diào)用函數(shù)來實(shí)現(xiàn)。
相關(guān)函數(shù):GetSystemInfo()
該函數(shù)返回有關(guān)目標(biāo)系統(tǒng)的諸如CUP類型,磁盤容量,當(dāng)前日期,當(dāng)前操作系統(tǒng),內(nèi)存容量等信息,返回的內(nèi)存容量是以千字節(jié)為單位。有關(guān)函數(shù)的具體使用請(qǐng)參閱函數(shù)手冊。
具體實(shí)現(xiàn)代碼如下:
/*****************程序代碼*******************/
if (GetSystemInfo (EXTENDEDMEMORY, nvFreeMem, svResult) < 0) then
MessageBox ("內(nèi)存檢測失敗,安裝程序?qū)⒔K止!.", SEVERE);
abort;
endif;
if ( nvFreeMem < 16384 ) then
szMsg = "該軟件只能安裝在16M以上內(nèi)存的機(jī)器中。\n很遺憾,本機(jī)器可用內(nèi)存不足16M!\n\n安裝程序?qū)⒔K止!";
MessageBox (szMsg, SEVERE);
abort;
endif;
// end.
/******************結(jié)束*********************/
四、 許可協(xié)議

選擇Setup File面板,打開Language Independent,選擇Operating System Independent ,在右邊列表中找到License.txt文件,雙擊它輸入自己的許可協(xié)議就行了。
五、 Readme文件

同上,找到Infolist.txt文件,雙擊它輸入需要說明的自述文件。
六、客戶信息

看一看圖片,不難發(fā)現(xiàn)當(dāng)安裝程序運(yùn)行這一步時(shí)上面已經(jīng)填上了缺省的用戶名和客戶名稱,甚至連序列號(hào)都有。這是怎么回事呢?原來在前面我們介紹的事件OnFirstUIBefore的開始有一段代碼,如下:
nSetupType = TYPICAL;
TARGETDIR = PROGRAMFILES ^@COMPANY_NAME ^@PRODUCT_NAME;
szDir = TARGETDIR;
SHELL_OBJECT_FOLDER = @FOLDER_NAME;
svName = "";
svCompany = "";
svSerial = "";
如果我們沒有給svName和svCompany賦新值的話缺省的用戶名和客戶名稱就是我們在安裝Windows時(shí)注冊的用戶和單位。當(dāng)然,如果沒有給svSerial賦值的話,圖片上的序列號(hào)就為空。
相關(guān)系統(tǒng)變量:
PROGRAMFILES:存放Windows程序文件夾(Program files)的完整路徑。不能更改。
七、 序列號(hào)判斷

用InstallShield安裝模板制作出的安裝程序在運(yùn)行過程如果沒有序列號(hào)是無法再繼續(xù)下去的。但如果我們在序列號(hào)上不加任何檢驗(yàn)的話,InstallShield會(huì)默認(rèn)為任何字符都是有效的而不管它是什么,此時(shí)序列號(hào)也就毫無意義,除非你想讓你的應(yīng)用程序無限制的發(fā)布。因此,還是建議你在安裝過程中對(duì)序列號(hào)進(jìn)行一下有效性檢驗(yàn)。方法很簡單,在事件OnFirstUIBefore中找到Dlg_SdRegisterUserEx分支,見下列代碼:
Dlg_SdRegisterUserEx::
szMsg = "";
szTitle = "";
nResult = SdRegisterUserEx( szTitle, szMsg, svName, svCompany, svSerial );
if (nResult = BACK) goto Dlg_SdShowInfoList;
在語句
if (nResult = BACK) goto Dlg_SdShowInfoList;
前添上相應(yīng)的序列號(hào)校驗(yàn)程序
//*******增加序列號(hào)的檢驗(yàn)
if ( svSerial != '199721') then
MessageBox("警告:輸入序列號(hào)錯(cuò)誤,請(qǐng)確認(rèn)后重輸!",SEVERE);
goto Dlg_SdRegisterUserEx;
endif;
//end.
就這么簡單。聲明一下,這里我只是給出的最簡單的判別模式,較為安全的模式是在判別時(shí)對(duì)序列號(hào)進(jìn)行必要的加解密轉(zhuǎn)換,有興趣的朋友可以自己去實(shí)現(xiàn)。
八、 安裝文件夾

在一般情況下,InstallShield默認(rèn)的安裝文件夾是存放Windows程序文件夾(Program files)的完整路徑,即C:\ Program files(如果Windows安裝在C盤的話)。但是,在絕大多數(shù)情況下我們都希望客戶將應(yīng)用程序安裝在單獨(dú)的數(shù)據(jù)盤上,即不與操作系統(tǒng)安裝在同一個(gè)硬盤分區(qū)里。一方面便于管理,另一方面也為了防止我們的程序因?yàn)橄到y(tǒng)盤格式化而受到連累。因此,我們常常會(huì)建議用戶在安裝應(yīng)用程序的時(shí)候選擇另一個(gè)硬盤,如D盤。
另外,我們有時(shí)希望我們所開發(fā)出來的應(yīng)用程序安裝在一個(gè)帶有自己公司名稱和應(yīng)用程序名稱的目錄下。InstallShield默認(rèn)的目錄就做的非常好,她會(huì)建立一個(gè)諸如“C:\Program Files\ABCD軟件工作室\Demo”的目錄(在這里我虛構(gòu)了一個(gè)公司“ABCD軟件工作室”)。但,問題是,一旦讓用戶選擇了其它的路徑,或者硬盤,他們幾乎都不會(huì)在目錄上加上開發(fā)商和應(yīng)用程序目錄,“\ABCD軟件工作室\Demo”。如果用戶僅僅選擇了磁盤而忘了選擇任何目錄的話,InstallShield就會(huì)將所有的程序和數(shù)據(jù)文件復(fù)制到磁盤根目錄下,用戶和我們當(dāng)然都不希望這樣。因此,為了避免這一切的發(fā)生我們只能寄希望于我們的安裝程序能夠有足夠的智能來應(yīng)付這一切,這樣就不管用戶是否選擇了目錄。實(shí)現(xiàn)方法如下。
在事件OnFirstUIBefore中找到Dlg_SdAskDestPath分支,如下
Dlg_SdAskDestPath:
szTitle = "";
szMsg = "";
nResult = SdAskDestPath( szTitle, szMsg, szDir, 0 );
TARGETDIR = szDir;
if (nResult = BACK) goto Dlg_SdRegisterUserEx;
我們首先需要定義一個(gè)臨時(shí)字符串變量svTemp
STRING svTemp;
然后,將語句
nResult = SdAskDestPath( szTitle, szMsg, szDir, 0 );
TARGETDIR = szDir;
修改成如下:
svTemp = szDir;
nResult = SdAskDestPath( szTitle, szMsg, szDir, 0 );
if ( svTemp != szDir) then
szDir = szDir^@COMPANY_NAME ^@PRODUCT_NAME;
endif;
TARGETDIR = szDir;
該語句的功能是在用戶選擇的路徑后加上單位和應(yīng)用程序名稱作為安裝的目錄(注:這里我并沒有考慮到用戶在選擇了默認(rèn)外的路徑后加上單位和應(yīng)用程序名稱作為安裝目錄的情況)。其中,變量COMPANY_NAME 和PRODUCT_NAME中存放的是單位名和產(chǎn)品名,我們可以隨時(shí)在資源面板中修改它的值。
變量TARGETDIR是指向在硬盤上目的文件夾的完整路徑。當(dāng)調(diào)用函數(shù)SdAskDestPath時(shí),該函數(shù)會(huì)創(chuàng)建一個(gè)對(duì)話框來讓用戶選擇應(yīng)用程序要存放的目的路徑。
不要以為加上了單位和程序的目錄就萬事大吉了,可別忘了既然讓用戶來選擇安裝的目的盤就很有可能出現(xiàn)磁盤空間不夠大,從而導(dǎo)致程序的安裝失敗或安裝后的剩余空間不夠程序?qū)頂?shù)據(jù)的存放等等。因此,必須在用戶選擇之后,程序進(jìn)入下一步之前對(duì)目的盤的可用空間進(jìn)行判斷。在這里我假設(shè)我們的程序需要10兆的空間來存放目前的文件和未來幾年可能的數(shù)據(jù)。
為了達(dá)到上述目的就必須知道:
1、 用戶最終選擇的是哪個(gè)硬盤
2、 該硬盤當(dāng)前的剩余空間是多少
那么,如何來實(shí)現(xiàn)呢?幸好InstallShield為我們提供了足夠多的函數(shù)來應(yīng)付這一切。
函數(shù)一:GetDisk
該函數(shù)從指定的路徑或帶有路徑的文件名當(dāng)中提取該路徑或文件所在的磁盤驅(qū)動(dòng)器號(hào)。調(diào)用成功返回0,否則返回小于0的任何數(shù)。
函數(shù)二:GetDiskSpace
該函數(shù)返回指定磁盤或指定路徑所在磁盤的剩余空間,用字節(jié)表示。
具體實(shí)現(xiàn)代碼如下:
//*******加入磁盤剩余空間判斷,目前判斷剩余空間是否少于10M
//******* 10M * 1024千字節(jié) * 1024字節(jié) = 10485760 字節(jié)
GetDisk (szDir, svDrive);
lFreeSpace = GetDiskSpace (svDrive);
if (lFreeSpace < 10485760) then
MessageBox("警告:安裝路徑所在的磁盤空間不足10M!請(qǐng)重新選擇!",SEVERE);
goto Dlg_SdAskDestPath;
endif;
// end.
我們只要將這段代碼放入語句
if (nResult = BACK) goto Dlg_SdRegisterUserEx;
之前就行了。
九、 安裝類型

該步驟是由InstallShield自動(dòng)給出的,一般情況下我們不必做任何事。三個(gè)安裝選項(xiàng):典型安裝、壓縮安裝和自定義安裝是根據(jù)我們在安裝類型(Setup Type)的面板中預(yù)先設(shè)置好的值來進(jìn)行的。如果用戶選擇了自定義安裝,系統(tǒng)就會(huì)彈出如下界面,見圖。

這是由系統(tǒng)自動(dòng)給出的,我們用不著寫一行代碼,這是不是很棒?
不知道你有沒有注意到窗口的左面有一個(gè)說明框,它是用來提示用戶目前所選擇的組件是干什么的。在缺省的狀態(tài)下它是空的,需要我們來添加。添加的方法是在組件(Components)的面板中,每當(dāng)我們點(diǎn)中一個(gè)組件在左邊的列表中就會(huì)有一個(gè)描述欄(Description),它的內(nèi)容就是上面提到的幫助信息,你只要將相對(duì)用戶說的話寫上去就行了。
十、 程序文件夾

這一步由InstallShield自動(dòng)給出,一般不要做任何修改。
十一、 最后確認(rèn)

我們一定還記得每當(dāng)安裝一個(gè)像Office等專業(yè)化軟件時(shí),在軟件正式安裝前系統(tǒng)都會(huì)給出一個(gè)列表框,其中列出了你所做的一切選擇,包括軟件的安裝路徑,需要安裝的組件等,同時(shí)還包括了注冊的用戶名和單位等信息。在我們用InstallShield制作安裝盤的時(shí)候也會(huì)有這一個(gè)列表框,但遺憾的是在缺省狀況下InstallShield提供的這個(gè)列表框是空的,什么內(nèi)容也沒有,這需要我們給它加入。好在有函數(shù)ListAddString來幫我們的忙。
相關(guān)函數(shù):ListAddString
該函數(shù)在字符串列表框的當(dāng)前對(duì)象前后新增加一個(gè)字符串。調(diào)用成功返回0,否則返回小于0的任何數(shù)。
在腳本Setup.rul的事件OnFirstUIBefore中找到Dlg_SdStartCopy分支,如下:
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) goto Dlg_SdSelectFolder;
// setup default status
SetStatusWindow(0, "");
Enable(STATUSEX);
StatusUpdate(ON, 100);
return 0;
在語句
nResult = SdStartCopy( szTitle, szMsg, listStartCopy );
前加上如下代碼
//*******加入安裝過程中用戶所選擇的主要步驟
// 如果不手動(dòng)加入的話將會(huì)什么也不列出
ListAddString(listStartCopy,"客戶信息:",AFTER);
ListAddString(listStartCopy,"用戶名:" + svName,AFTER);
ListAddString(listStartCopy,"用戶單位:" + svCompany,AFTER);
ListAddString(listStartCopy,"",AFTER);
ListAddString(listStartCopy,"程序安裝路徑:" + szDir,AFTER);
ListAddString(listStartCopy,"",AFTER);
ListAddString(listStartCopy,"程序文件夾:" + szfolder,AFTER);
ListAddString(listStartCopy,"",AFTER);
switch (nSetupType)
case TYPICAL : ListAddString(listStartCopy,"安裝類型:典型安裝",AFTER);
case COMPACT: ListAddString(listStartCopy,"安裝類型:壓縮安裝",AFTER);
case CUSTOM: ListAddString(listStartCopy,"安裝類型:自定義安裝",AFTER);
endswitch;
//end.
其中svName、svCompany、szDir等變量我們可以在事件OnFirstUIBefore開始的變量定義中找到。從變量的名稱我們很清楚的知道該變量存放的是用戶名,單位,安裝目錄等。
十二、 第一幅背景,第二幅背景——圖片12,圖片13
細(xì)心的朋友一定會(huì)注意到軟件在安裝過程中會(huì)出現(xiàn)兩副不同的背景圖片,圖12和圖13,這就是InstallShield的顯示區(qū)界面,我們可以稱它為布告板。這看上去是不是很像在播放幻燈片?呵呵,我們可以和微軟的比一比了(說句笑話)。言歸正傳,還是來說說是如何實(shí)現(xiàn)的吧。
布告板,它只有在文件被傳輸時(shí)才被激活。也就是說,當(dāng)你調(diào)用ComponentTransferData函數(shù)來解壓并拷貝時(shí)布告板才被顯示,該函數(shù)是有系統(tǒng)自動(dòng)調(diào)用,用不著我們來操心。
但是,你不能為一個(gè)布告板指定顯示時(shí)間,InstallShield會(huì)根據(jù)整個(gè)程序的安裝時(shí)間(指文件拷貝時(shí)間)自動(dòng)的為每一個(gè)文件平均分配,但至少是2秒。如果你的安裝程序僅持續(xù)20秒,而你卻放置了25副圖片,很顯然系統(tǒng)只會(huì)顯示前10副圖片。
當(dāng)你需要顯示布告板之前還必須確保以下兩個(gè)條件:
1、 在你的腳本里,首先要確保在文件被傳輸前調(diào)用Enable(BACKGROUND) 和 Enable(FULLWINDOWMODE),我們可以加在事件OnMoving中。形式如下:
function OnMoving()
STRING szAppPath;
begin
Enable(BACKGROUND);
Enable(FULLWINDOWMODE);
Enable(STATUSDLG);
PlaceWindow(STATUSDLG, 400, 10, LOWER_LEFT);
szAppPath = TARGETDIR;
RegDBSetItem(REGDB_APPPATH, szAppPath);
RegDBSetItem(REGDB_APPPATH_DEFAULT, szAppPath ^ @PRODUCT_KEY);
end;
相關(guān)函數(shù):
Enable(BACKGROUND) :顯示安裝主背景窗口
Enable(FULLWINDOWMODE):設(shè)置主背景窗口為最大化。
2、 在設(shè)置文件(Setup Files)面板中,在合適的目標(biāo)語言和平臺(tái)下放置具有特殊后綴名的布告板文件。默認(rèn)的命名是:“Bbrd”,然后再跟一個(gè)數(shù)字,最后再加上后綴“.bmp”或“.wmf”。例如,我們現(xiàn)在要加三副BMP圖片,則這三副圖片的名稱分別應(yīng)該是Bbrd1.bmp、Bbrd2.bmp、Bbrd3.bmp。
好了,運(yùn)行一下,很不錯(cuò)。我們可以利用這項(xiàng)技術(shù)在安裝過程中播放類似幻燈片效果,就像安裝Windows一樣。
十三、 復(fù)制完成

這一步由InstallShield自動(dòng)給出。

十四、 重新啟動(dòng)

在很多情況下,當(dāng)我們修改了注冊表或是在系統(tǒng)中安裝了其它驅(qū)動(dòng)程序的時(shí)候,為了確保應(yīng)用程序能夠順利運(yùn)行,我們還是希望用戶在安裝結(jié)束之后能夠重新啟動(dòng)一下系統(tǒng)。這時(shí)函數(shù)SdFinishReboot就顯得十分有用。
相關(guān)函數(shù):SdFinishReboot
該函數(shù)顯示一個(gè)重新啟動(dòng)的對(duì)話框,它提供給用戶兩種選擇:系統(tǒng)自動(dòng)啟動(dòng)和用戶自己啟動(dòng)。當(dāng)函數(shù)返回WILL_REBOOT表明用戶選擇了重新啟動(dòng);當(dāng)返回NEXT(或1)表明用戶選擇了自己啟動(dòng);當(dāng)返回小于0表明當(dāng)用戶選擇了重新啟動(dòng),但重新啟動(dòng)失敗。在缺省的情況下是用戶自己啟動(dòng)。
一般情況下,我們是在事件OnEnd中調(diào)用SdFinishReboot函數(shù)。OnEnd顧名思義是在Setup腳本里最后被執(zhí)行的事件。程序代碼如下:
/*****************重啟動(dòng)代碼*******************/
function OnEnd()
STRING szTitle, szMsg1, szMsg2;
NUMBER nOption, nReserved;
begin
szTitle = "已經(jīng)完成全部的拷貝工作,";
szMsg1 = "在使用本軟件前必須重新啟動(dòng)。";
nOption = 0;
szMsg2 = '請(qǐng)選擇一種啟動(dòng)方式,然后單擊"確定"完成安裝。';
nReserved = 0;
if (SdFinishReboot (szTitle, szMsg1, nOption, szMsg2, nReserved) < 0) then
MessageBox ("重啟動(dòng)失敗,請(qǐng)重新啟動(dòng)系統(tǒng)后再使用本軟件!", SEVERE);
endif;
end;
/**************** 結(jié)束 *******************/
其中,szTitle、szMsg1、szMsg2不設(shè)置也罷,只是系統(tǒng)會(huì)以缺省的方式出現(xiàn)。
第三步:深度探索
如果說我們完成了圖1到圖15全部功能后就可以馬上動(dòng)手制作安裝盤的話那我們所做的也只是給應(yīng)用程序加了一個(gè)花邊,并沒有實(shí)際功效。它只是把原先由人工的復(fù)制工作交給系統(tǒng)自動(dòng)去執(zhí)行,更說不上文章開頭所說的實(shí)現(xiàn)系統(tǒng)的自動(dòng)配置。我們還是得在應(yīng)用程序發(fā)行時(shí)去用戶現(xiàn)場安裝、配置一些接口程序。
大家都知道,我們開發(fā)的程序有百分之九十以上是和數(shù)據(jù)庫打交道。目前,數(shù)據(jù)庫種類的繁多,各軟件廠商又各自推出自己的數(shù)據(jù)庫接口程序,這就使得我們要確保開發(fā)出來的應(yīng)用程序最終能夠安全順利的運(yùn)行就必須攜帶上自己的數(shù)據(jù)庫接口程序,雖然有一些接口標(biāo)準(zhǔn),但這遠(yuǎn)遠(yuǎn)不夠。因此,如何將這些工作交給安裝程序去完成就成為能否制作出具有專業(yè)水準(zhǔn)的安裝程序的關(guān)鍵,也是為什么我會(huì)把它作為一個(gè)標(biāo)題單獨(dú)分開。
那么如何在制作安裝程序的時(shí)候?qū)崿F(xiàn)數(shù)據(jù)庫驅(qū)動(dòng)程序的安裝和配置呢?要實(shí)現(xiàn)它我們還是先從注冊表和ODBC兩個(gè)基本概念入手,下面進(jìn)行分別討論。
一、注冊表
在早期的Windows系列應(yīng)用程序中用后綴為.ini的文件保存Windows系統(tǒng)和其他該應(yīng)用程序的配置信息。后來,Windows95的出現(xiàn),系統(tǒng)就用一個(gè)稱做注冊表的來代替保存應(yīng)用程序配置信息的.ini文件,盡管Windows95仍然支持使用.ini文件。用注冊表來保留這些信息可以為我們提供一個(gè)配置信息的單一源,這不同于那些分布在磁盤里的各種.ini文件的雜燴。同時(shí),注冊表也提供了一個(gè)簡單機(jī)制來保存當(dāng)前用戶或當(dāng)前配置的信息。注冊表甚至允許你通過網(wǎng)絡(luò)管理其他機(jī)器的注冊表。另外,在NT下,注冊表能提供安全級(jí)別,這在先前的配置存儲(chǔ)機(jī)制中是沒有的。因此,使得能否合理的使用注冊表成為WIN32應(yīng)用程序的特征之一。
注冊表使用的是樹型體系結(jié)構(gòu),樹中的每個(gè)結(jié)點(diǎn)稱鍵。每個(gè)鍵也可以包含其他的鍵或子鍵。它允許進(jìn)一步的分支,也即為值,它用來存儲(chǔ)有效的數(shù)據(jù)。在注冊表中,注冊表用鍵來組織數(shù)據(jù),一個(gè)鍵中的值用它們的名來識(shí)別,鍵名由可以打印的ASCII字符組成的簡單字符串。另外,以英文句號(hào)(.)開始的鍵名被系統(tǒng)所保留。鍵中的值可以用不同的數(shù)據(jù)來表示,可以是從一個(gè)簡單的整數(shù)到用戶定義的二進(jìn)制對(duì)象。在注冊表中只有四個(gè)基本鍵會(huì)受到應(yīng)用程序安裝的影響,這四個(gè)鍵分別是HKEY_CLASSES_ROOT、HKEY_CURRENT_USER、HKEY_LOCAL_MACHINE和HKEY_USERS。而其中對(duì)我們配置ODBC有用的只有HKEY_LOCAL_MACHINE和HKEY_CURRENT_USER。
1、 HKEY_LOCAL_MACHINE
在HKEY_LOCAL_MACHINE中保存的是關(guān)于本地機(jī)器的配置信息,獨(dú)立于任何特殊的用戶都存儲(chǔ)在其中。此配置信息又進(jìn)一步分成幾個(gè)不同的子鍵,它們是Config,Enum,Hardware,Network,Security,Software和System。
其中,Software子鍵用于包含用戶應(yīng)用程序的配置信息,這是最有可能被我們的應(yīng)用程序使用的地方。由于我們的應(yīng)用程序所要的信息一般來說對(duì)其他程序并不需要,同時(shí)也為了更好的管理這些信息,因此我們應(yīng)該在HKEY_LOCAL_MACHINE\SOFTWARE下增加一個(gè)子鍵,鍵名當(dāng)然是能代表我們的應(yīng)用程序。
2、 HKEY_CURRENT_USER
鍵HKEY_CURRENT_USER通常為我們的應(yīng)用程序存儲(chǔ)和恢復(fù)特殊用戶相應(yīng)的特殊配置提供了方便。同樣,在HKEY_CURRENT_USER中也存在一些子鍵,最常用的鍵是Software,打開Software鍵我們會(huì)發(fā)現(xiàn)有一個(gè)子鍵ODBC,顧名思義里面存放的當(dāng)前機(jī)器上的ODBC.INI文件的內(nèi)容,
好了,有關(guān)注冊表的一些知識(shí)就簡單的說到這里,在開始開始配置我們的ODBC之前,為了便于讀者能夠順利的讀懂本文所附帶的程序代碼,現(xiàn)將有關(guān)InstallShell注冊表函數(shù)作一個(gè)簡單的介紹。
1、 RegDBKyeExist
該函數(shù)用來查看某個(gè)指定的鍵是否在注冊表中。
2、 RegDBSetDefaultRoot
該函數(shù)為其他的注冊表函數(shù)設(shè)置一個(gè)不同的根鍵。大多數(shù)InstallShield注冊表函數(shù)工作在缺省的以鍵HKEY_CLASSES_ROOT為根的注冊鍵樹上,用這個(gè)函數(shù)你就可以指定一個(gè)特殊的鍵為根,像鍵HKEY_LOCAL_MACHINE或 HKEY_CURRENT_USER或HKEY_USERS。
3、 RegDBSetKeyValueEx
該函數(shù)為某個(gè)在注冊表中的鍵設(shè)置鍵值。如果該鍵不存在,該函數(shù)將為你創(chuàng)建該鍵。但是,新創(chuàng)建的鍵不會(huì)被安裝軟件卸載程序所登記,除非它是一個(gè)已登記過的鍵的子鍵。要想讓安裝軟件卸載程序所登記可以先用RegDBCreateKeyEx創(chuàng)建然后再設(shè)置該鍵值。
4、 RegDBCreateKeyEx
該函數(shù)用來在注冊表中創(chuàng)建一個(gè)鍵。當(dāng)使用該函數(shù)來創(chuàng)建一個(gè)鍵或子鍵時(shí),為了保證能被正確地安裝軟件卸載程序登記要首先確保它的父鍵首先已經(jīng)被成功創(chuàng)建。
二、ODBC
1、ODBC介紹
ODBC,即開放式數(shù)據(jù)庫連接,它是由Microsoft公司提供的應(yīng)用程序接口(API),一個(gè)單獨(dú)的應(yīng)用程序通過它可以訪問許多個(gè)不同類型的數(shù)據(jù)庫及不同格式的文件。
雖然繼ODBC之后業(yè)界已推出了一些像OLE DB,ADO等之類的新技術(shù),但目前,開放式數(shù)據(jù)庫連接API也許是在Windows應(yīng)用程序中用得最廣泛的數(shù)據(jù)庫接口。在每種數(shù)據(jù)庫所用到的專用接口中,除了加入特殊代碼外,還需要為ODBC API譯碼。在ODBC API和用來與數(shù)據(jù)庫交換信息的專用接口之間,特殊的ODBC驅(qū)動(dòng)程序提供了任何一種必需的譯碼。
2、ODBC 4.0驅(qū)動(dòng)程序
以下的表列出了 ODBC 桌面數(shù)據(jù)庫驅(qū)動(dòng)程序 4.0 的每一個(gè)組件所要求的文件。這些文件安裝在 Windows的系統(tǒng)目錄\Windows\System或 Windows NT的系統(tǒng)目錄\Windows\System32下。如果 ODBC 文件以前被安裝在一個(gè)不同的目錄中,請(qǐng)確定你使用的是在 \Windows\System (或 System32) 目錄下的新文件。
某些文件是多個(gè)部件共同需要的。如果你想要和你的應(yīng)用程序一起重新分配任一個(gè) ODBC 桌面數(shù)據(jù)庫驅(qū)動(dòng)程序,這些文件也必須被重新分配。建議在分發(fā)軟件時(shí)在你的應(yīng)用程序目錄下建立一個(gè) “\ODBC\”目錄,將這些重新拷貝到該目錄底下,但一定要確保該路徑是個(gè)PATH搜索路徑。
以下的文件對(duì)于每一個(gè) ODBC 桌面數(shù)據(jù)庫驅(qū)動(dòng)程序 4.0 是共同的:
Ds16gt.dll
Ds32gt.dll
Expsrv.dll
Msjint40.dll
Msjet40.dll
Msjter40.dll
Msjtes40.dll
Msvcrt40.dll
Odbc16gt.dll
Odbc32.dll
Odbc32gt.dll
Odbccp32.cpl
Odbccp32.dll
Odbccr32.dll
Odbcinst.cnt
Odbcinst.hlp
Odbcint.dll
Odbcjet.hlp
Odbcjet.cnt
Odbcji32.dll
Odbcjt32.dll
Odbcjtnw.hlp
Odbcjtnw.cnt
Odbctl32.dll
Vbajet32.dll
Odbctrac.dll
下列文件是安裝某一個(gè)驅(qū)動(dòng)程序類型的軟件所必須的:
驅(qū)動(dòng)程序
文件
Microsoft Access
Msrd2x40.dll,Msrd3x40.dll
DBASE
Msxbse40.dll,Oddbse32.dll
Microsoft Excel
Msexcl40.dll,Odexl32.dll
Paradox
Mspdox40.dll,Odpdx32.dll
Text
Mstext40.dll,Odtext32.dll
Adaptive Server Anywhere
見下面說明
注意:
1、 ODBC 桌面數(shù)據(jù)庫驅(qū)動(dòng)程序4.0版本至少需要 16 MB 的隨機(jī)訪問內(nèi)存 (RAM)
2、 有關(guān)與這些驅(qū)動(dòng)程序一起使用的ODBC版本的信息,參考ODBC程序員參考手冊。
3、Adaptive Server Anywehre ODBC驅(qū)動(dòng)程序
下表列出的是工作在Adaptive Server Anywehre環(huán)境下的驅(qū)動(dòng)程序,必須將這些文件拷貝到一個(gè)獨(dú)立的目錄下,并且使系統(tǒng)能夠搜索到。
描述
32位Windows
ODBC驅(qū)動(dòng)程序
Dbodbc6.dll
ODBC翻譯程序
Dbodtr6.dll
特殊語言庫文件
Dblgen6.dll
網(wǎng)絡(luò)接口文件
Dbport6.dll
連接對(duì)話框程序文件
Dbcon6.dll
注意:
1、 ODBC翻譯程序僅僅在你的應(yīng)用程序是依賴于ANSI標(biāo)準(zhǔn)的字符串轉(zhuǎn)換。
2、 網(wǎng)絡(luò)接口程序庫是專門用于網(wǎng)絡(luò)通信用,它僅僅是在客戶端的程序訪問網(wǎng)絡(luò)服務(wù)器上才必須存在。
3、 連接對(duì)話框程序文件在以下的幾種情況下才需要加入:
a. 你的最終用戶需要?jiǎng)?chuàng)建自己的數(shù)據(jù)源
b. 當(dāng)用戶連接數(shù)據(jù)庫時(shí)需要輸入用戶標(biāo)識(shí)和口令
c. 不管是出于什么目的用戶需要顯示連接對(duì)話框
4、配置ODBC驅(qū)動(dòng)程序
為了使用ODBC驅(qū)動(dòng)程序安裝程序不僅僅只是將這些驅(qū)動(dòng)程序文件拷貝到硬盤上,它還必須在注冊表中設(shè)置一組ODBC驅(qū)動(dòng)程序的屬性。
Adaptive Server Anywhere安裝程序會(huì)自動(dòng)在NT和WIN9X的系統(tǒng)注冊表中標(biāo)識(shí)和配置ODBC驅(qū)動(dòng)程序。因此,如果你為你的最終用戶制作應(yīng)用程序的安裝程序時(shí)也必須進(jìn)行相同的設(shè)置。
通過查看Windows注冊表工具,我們發(fā)現(xiàn)Adaptive Server Anywhere的ODBC驅(qū)動(dòng)程序是在下列的鍵中被系統(tǒng)所標(biāo)識(shí)的。
HKEY_LOCAL_MACHINE\Software\ODBC\ODBCINST.INI\Adaptive Server Anywhere 6.0,其中需要設(shè)置的下鍵有
鍵名
類型
鍵值
Driver
String
Path\dbodbc6.dll
Setup
String
Path\dbodbc6.dll
除此之外,你還必須在鍵HKEY_LOCAL_MACHINE\Software\ODBC\ODBCINST.INI\ODBC Drivers中為Adaptive Server Anywhere注冊
在該鍵中增加如下鍵
鍵名
類型
鍵值
Adaptive Server Anywhere 6.0
String
Installed
5、數(shù)據(jù)源注冊
除了進(jìn)行ODBC驅(qū)動(dòng)程序注冊外,還必須為用戶的數(shù)據(jù)源進(jìn)行注冊。這是因?yàn)槊恳粋€(gè)用戶數(shù)據(jù)源必須被注冊表登記才能被系統(tǒng)所識(shí)別,這樣用戶才能使用它。因此,必須在鍵HKEY_CURRENT_USER\Software\ODBC\ODBC.INI\中進(jìn)行如下注冊。
鍵名
值類型
鍵值
AutoStop
String
Yes
DatabaseFile
String
Path\demo.db
Description
String
Adaptive Server Anywhere Sample Database
Driver
String
Path\win32\dbodbc6.dll
PWD
String
Sql
Start
String
Path\win32\dbeng6.exe -q
UID
String
Dba
注:
1、 上面的path除了DatabaseFile指的是客戶數(shù)據(jù)庫所在的路徑,其他的都是指Adaptive Server Anywhere的安裝路徑。我們在給客戶分發(fā)應(yīng)用軟件的時(shí)候一般不再另外安裝Adaptive Server Anywhere,所以可以將Adaptive Server Anywhere路徑下的文件Dbeng6.exe,Dbodbc6.dll,Dblgon6.dll,Dbport6.dll,Dbcon6.dll,Dbodtr6.dll一起分發(fā)給客戶,并且拷貝至一個(gè)單獨(dú)目錄下,然后將路徑指向它就可以了。
2、 在dbeng6.exe后加上“-q”是為了隱藏任務(wù)欄上的SQLAnywhere窗口。
另外,必須將數(shù)據(jù)源加到注冊表中的數(shù)據(jù)源列表中,加入到如下鍵中
HKEY_CURRENT_USER\Software\ODBC\ODBC.INI\ODBC Data Sources\
該鍵中存放的是每一個(gè)數(shù)據(jù)源和ODBC驅(qū)動(dòng)程序的關(guān)聯(lián)。鍵名是指數(shù)據(jù)源名字;鍵值是指ODBC驅(qū)動(dòng)程序的名字。由于本文所敘述的是基于PowerBuilder7.0開發(fā)環(huán)境下的應(yīng)用程序的發(fā)布,所以鍵值都是"Adaptive Server Anywhere 6.0"(因?yàn)?,?dāng)我們安裝PowerBuilder 7.0時(shí),系統(tǒng)默認(rèn)的ODBC驅(qū)動(dòng)程序的名字為Adaptive Server Anywhere 6.0),當(dāng)然,如果你愿意話也可以改變它。
這里有必要提示一下,由于用戶數(shù)據(jù)源的配置可能包含一些敏感的數(shù)據(jù)庫設(shè)置,比如說連接數(shù)據(jù)庫的用戶ID和口令。這些設(shè)置都會(huì)以無格式的文本形式存儲(chǔ)在注冊表中,可以很容易的被Windows注冊表編輯程序regedit.exe或regedt32.exe查看,只要有點(diǎn)編程經(jīng)驗(yàn)的人都能通過獲這些實(shí)用工具取該ID和口令來修改數(shù)據(jù)庫中數(shù)據(jù)。因此,你在處理這些問題的時(shí)候還要三思一下,你可以選擇加密口令或讓用戶在連接數(shù)據(jù)庫時(shí)錄入。
既然我們知道了如何在注冊表中為應(yīng)用程序進(jìn)行ODBC配置,那么剩下的問題是,把他們放在什么地方?不用說,大家也猜到了,最好的地方就是當(dāng)所有文件都已經(jīng)復(fù)制完畢,在我們要求用戶重新啟動(dòng)系統(tǒng)之前。事件OnMoved可以做到這一切。在做這些事的同時(shí)我們最好能夠顯示給用戶一個(gè)消息框,告訴用戶我們在干什么,做完這一切之后再關(guān)閉它。這就要用到函數(shù)SdShowMsg和Delay。見圖。

相關(guān)事件:OnMoved
該事件是在當(dāng)所有在目標(biāo)機(jī)器上的組件都被安裝或反安裝時(shí)響應(yīng),在該事件中的代碼總是會(huì)被執(zhí)行。
相關(guān)函數(shù):
SdShowMsg:該函數(shù)打開或關(guān)閉一個(gè)非模態(tài)的小窗口,該窗口顯示指定的消息。
Delay:該函數(shù)可以用指定的時(shí)間(秒)來使安裝程序的執(zhí)行時(shí)間延遲。
下面是完整的ODBC注冊表配置的代碼程序。
/*********************程序代碼********************/
//*******當(dāng)所有數(shù)據(jù)拷貝完畢后在這里配置ODBC
function OnMoved()
STRING szMsg;
STRING svDB;
STRING svASAOdbcDll;
STRING svASA;
STRING szKey;
STRING szClass;
STRING svResult;
STRING szNumName, szNumValue, svNumValue, szTitle;
NUMBER nType, nSize, nvType, nvSize;
begin
szMsg = "正在進(jìn)行系統(tǒng)配置,請(qǐng)等待...";
SdShowMsg (szMsg, TRUE);
svDB = TARGETDIR + "\\db\\Demo.db";
svASAOdbcDll = TARGETDIR + "\\ASA\\dbodbc6.dll";
svASA = TARGETDIR + "\\ASA\\dbeng6.exe";
RegDBSetDefaultRoot (HKEY_LOCAL_MACHINE);
// 建立MyDemo ASA主鍵
szKey = "Software\\ODBC\\ODBCINST.INI\\MyDemo ASA";
szClass = "";
if (RegDBCreateKeyEx(szKey, szClass) < 0) then
MessageBox ("注冊表操作失敗,安裝程序?qū)⒔K止!", SEVERE);
abort;
endif;
// 建立MyDemo ASA下的鍵值
szNumName = "Driver";
szNumValue = svASAOdbcDll;
nType = REGDB_STRING;
nSize = -1;
if (RegDBSetKeyValueEx (szKey, szNumName, nType, szNumValue,
nSize) < 0) then
MessageBox ("注冊表操作失敗,安裝程序?qū)⒔K止!", SEVERE);
abort;
endif;
szNumName = "Setup";
if (RegDBSetKeyValueEx (szKey, szNumName, nType, szNumValue,
nSize) < 0) then
MessageBox ("注冊表操作失敗,安裝程序?qū)⒔K止!", SEVERE);
abort;
endif;
szKey = "Software\\ODBC\\ODBCINST.INI\\ODBC Drivers";
szNumName = "MyDemo ASA";
szNumValue = "Installed";
if (RegDBSetKeyValueEx (szKey, szNumName, nType, szNumValue,
nSize) < 0) then
MessageBox ("注冊表操作失敗,安裝程序?qū)⒔K止!", SEVERE);
abort;
endif;
//*************配置ODBC
RegDBSetDefaultRoot (HKEY_CURRENT_USER);
// 建立Mydemo
szKey = "Software\\ODBC\\ODBC.INI\\MyDemo";
if (RegDBCreateKeyEx(szKey, szClass) < 0) then
MessageBox ("注冊表操作失敗,安裝程序?qū)⒔K止!", SEVERE);
abort;
endif;
szNumName = "AutoStop";
szNumValue = "Yes";
nType = REGDB_STRING;
nSize = -1;
if (RegDBSetKeyValueEx (szKey, szNumName, nType, szNumValue,
nSize) < 0) then
MessageBox ("注冊表操作失敗,安裝程序?qū)⒔K止!", SEVERE);
abort;
endif;
szNumName = "DatabaseFile";
szNumValue = svDB;
if (RegDBSetKeyValueEx (szKey, szNumName, nType, szNumValue,
nSize) < 0) then
MessageBox ("注冊表操作失敗,安裝程序?qū)⒔K止!", SEVERE);
abort;
endif;
szNumName = "Description";
szNumValue = "My Paper's Sample";
if (RegDBSetKeyValueEx (szKey, szNumName, nType, szNumValue,
nSize) < 0) then
MessageBox ("注冊表操作失敗,安裝程序?qū)⒔K止!", SEVERE);
abort;
endif;
szNumName = "Driver";
szNumValue = svASAOdbcDll;
if (RegDBSetKeyValueEx (szKey, szNumName, nType, szNumValue,
nSize) < 0) then
MessageBox ("注冊表操作失敗,安裝程序?qū)⒔K止!", SEVERE);
abort;
endif;
szNumName = "PWD";
szNumValue = "SQL";
if (RegDBSetKeyValueEx (szKey, szNumName, nType, szNumValue,
nSize) < 0) then
MessageBox ("注冊表操作失敗,安裝程序?qū)⒔K止!", SEVERE);
abort;
endif;
szNumName = "Start";
szNumValue = svASA + " -d -c8m";
if (RegDBSetKeyValueEx (szKey, szNumName, nType, szNumValue,
nSize) < 0) then
MessageBox ("注冊表操作失敗,安裝程序?qū)⒔K止!", SEVERE);
abort;
endif;
szNumName = "UID";
szNumValue = "DBA";
if (RegDBSetKeyValueEx (szKey, szNumName, nType, szNumValue,
nSize) < 0) then
MessageBox ("注冊表操作失敗,安裝程序?qū)⒔K止!", SEVERE);
abort;
endif;
//***************注冊數(shù)據(jù)源
szKey = "Software\\ODBC\\ODBC.INI\\ODBC Data Sources";
szNumName = "MyDemo";
szNumValue = "MyDemo ASA";
if (RegDBSetKeyValueEx (szKey, szNumName, nType, szNumValue,
nSize) < 0) then
MessageBox ("注冊表操作失敗,安裝程序?qū)⒔K止!", SEVERE);
abort;
endif;
// UInstalled -- 反安裝后刪除新建的鍵
if ( FindFile(TARGETDIR + "\\db\\", "Demo.db", svResult) < 0 ) then
RegDBSetDefaultRoot (HKEY_LOCAL_MACHINE);
szKey = "Software\\ODBC\\ODBCINST.INI\\MyDemo ASA";
if (RegDBDeleteKey (szKey) < 0) then
MessageBox ("刪除注冊表數(shù)據(jù)失敗!", SEVERE);
endif;
szKey = "\\Software\\ODBC\\ODBCINST.INI\\ODBC Drivers";
if (RegDBDeleteValue (szKey, "MyDemo ASA") < 0) then
MessageBox ("刪除注冊表數(shù)據(jù)失敗!", SEVERE);
endif;
RegDBSetDefaultRoot (HKEY_CURRENT_USER);
szKey = "Software\\ODBC\\ODBC.INI\\MyDemo";
if (RegDBDeleteKey (szKey) < 0) then
MessageBox ("刪除注冊表數(shù)據(jù)失敗!", SEVERE);
endif;
szKey = "Software\\ODBC\\ODBC.INI\\ODBC Data Sources";
if (RegDBDeleteValue (szKey, "MyDemo") < 0) then
MessageBox ("刪除注冊表數(shù)據(jù)失敗!", SEVERE);
endif;
endif;
// UInstalled -- end
Delay (1);
SdShowMsg (szMsg, FALSE);
end;
/********************* 結(jié)束 ********************/
在進(jìn)行完成注冊表的添加之后還必須做的最后一件事就是為我們的應(yīng)用程序指定一個(gè)搜索路徑,因?yàn)槲覀冊诎惭b的時(shí)候拷貝了一些DLL庫文件。顯兒易見這就要求我們在Autoexec.bat中文件添加一個(gè)搜索路徑。
涉及到的函數(shù):
* FindFile:在指定的路徑下查找指定的文件,當(dāng)函數(shù)返回0時(shí)表示文件找到,當(dāng)返回小于0的任何數(shù)時(shí)表示沒有找到。
* CreateFile:創(chuàng)建一個(gè)新的文件,如果該文件已經(jīng)存在,那么CreateFile將覆蓋掉原先的。同樣,在創(chuàng)建之前要先用OpenFileMode設(shè)置文件模式。
* OpenFileMode:在你想要打開一個(gè)已存在的文件或建立一個(gè)新文件設(shè)置文件的模式。文件的模式根據(jù)文件類型的不同會(huì)有如下幾種:
文本文件:添加模式,只讀模式
二進(jìn)制文件:只讀模式,讀寫模式
* OpenFile:打開一個(gè)已經(jīng)存在的文本文件或二進(jìn)制文件。但打開之前必須先要用OpenFileMode設(shè)置文件打開的模式。
* WriteLine:該函數(shù)在一個(gè)以添加模式(append mode)打開或建立的文本文件中寫上一行文本。
* CloseFile:當(dāng)你完成用GetLine讀文件或用WriteLine寫文件的操作后必須用CloseFile函數(shù)將使用的文件關(guān)閉。
* LongPathToQuote:在長文件名上放置或去掉雙引號(hào)。因?yàn)槿绻菦]有加引號(hào)的長文件名PAHT命令是不會(huì)認(rèn)的。
具體的實(shí)現(xiàn)代碼如下:
/**********************程序代碼******************/
// 在Autoexec.bat中加入搜索路徑
function OnMoved()
STRING svResult;
NUMBER nvFileHandle;
STRING svDir;
Begin
... ...
OpenFileMode(FILE_MODE_APPEND);
if (FindFile("c:\\", "autoexec.bat", svResult) < 0) then //沒有,需要create一個(gè)
CreateFile(nvFileHandle, "c:\\","Autoexec.bat" );
else
OpenFile ( nvFileHandle , "C:\\" , "Autoexec.bat" );
endif;
svDir = TARGETDIR + "\\DLL"; // 將路徑指向DLL目錄
LongPathToQuote (svDir , TRUE );
WriteLine( nvFileHandle," ");
WriteLine( nvFileHandle ,"Set PATH=" +svDir +";%PATH%");
WriteLine( nvFileHandle," ");
CloseFile(nvFileHandle);
end;
/********************** 結(jié)束 ******************/
到目前為止,我們已經(jīng)完成了制作一個(gè)應(yīng)用程序的安裝實(shí)例所需要的全部工作。剩下的也只是一些錦上添花的事了。讓我們最后再看看還有什么要做的?對(duì)了,還應(yīng)該像其他專業(yè)軟件那樣在開始菜單中或者是在桌面上或者是在程序文件夾中添加快捷方式,這樣用戶在安裝完畢之后可以很方便的找到它。在這里我們將會(huì)用到函數(shù)AddFolderIcon。
相關(guān)函數(shù):AddFolderIcon
該函數(shù)在指定的程序文件中插入或替換圖標(biāo)。
下面是具體的實(shí)現(xiàn)代碼:
/******************程序代碼******************/
function OnMoved()
STRING szProgramFolder, szItemName, szCommandLine, szWorkingDir, szIconPath;
STRING szShortCutKey, szProgram, szParam;
NUMBER nIcon;
begin
//SzProgramFolder = FOLDER_STARTMENU;
// Set up parameters for call to AddFolderIcon.
szProgram = FOLDER_STARTMENU;
szParam = TARGETDIR + "\\Demo.exe";
LongPathToQuote (szProgram, TRUE);
LongPathToShortPath (szParam);
szCommandLine = szParam;
szWorkingDir = TARGETDIR + "\\DLL"; // 加上應(yīng)用程序的工作路徑
szIconPath = "";
nIcon = 0;
szShortCutKey = "";
// 在開始菜單中添加快捷方式
szProgramFolder = FOLDER_STARTMENU;
szItemName = "My Demo in StartMenu";
if (AddFolderIcon (szProgramFolder, szItemName, szCommandLine, szWorkingDir,
szIconPath, nIcon, szShortCutKey, REPLACE) < 0) then
MessageBox ("安裝程序在進(jìn)行開始菜單中添加快捷方式失敗,稍侯請(qǐng)自己添加!.", SEVERE);
endif;
// 在程序文件夾中添加快捷方式
szProgramFolder = FOLDER_PROGRAMS;
szItemName = "My Demo in Programs";
if (AddFolderIcon (szProgramFolder, szItemName, szCommandLine, szWorkingDir,
szIconPath, nIcon, szShortCutKey, REPLACE) < 0) then
MessageBox ("安裝程序在進(jìn)行程序文件中添加快捷方式失敗,稍侯請(qǐng)自己添加!.", SEVERE);
endif;
// 在桌面上添加快捷方式
szProgramFolder = FOLDER_DESKTOP;
szItemName = "My Demo in Desktop";
if (AddFolderIcon (szProgramFolder, szItemName, szCommandLine, szWorkingDir,
szIconPath, nIcon, szShortCutKey, REPLACE) < 0) then
MessageBox ("安裝程序在進(jìn)行桌面上添加快捷方式失敗,稍侯請(qǐng)自己添加!.", SEVERE);
endif;
end;
/****************** 結(jié)束 ******************/
當(dāng)然了,我們還得在卸載程序中加上刪除這些快捷方式的代碼,否則的話當(dāng)用戶刪除了我們的應(yīng)用程序后會(huì)對(duì)我們的程序怒發(fā)沖冠的,我當(dāng)然不希望這樣。
/***************程序代碼***************/
// 刪除桌面上的快捷方式
if (DeleteFolderIcon (FOLDER_DESKTOP, "My Demo in Desktop") < 0) then
MessageBox ("安裝程序在刪除桌面上的快捷方式的時(shí)候出錯(cuò),稍侯請(qǐng)自己刪除!.", SEVERE);
endif;
// 刪除開始菜單中的快捷方式
if (DeleteFolderIcon (FOLDER_STARTMENU, "My Demo in StartMenu") < 0) then
MessageBox ("安裝程序在刪除開始菜單中的快捷方式的時(shí)候出錯(cuò),稍侯請(qǐng)自己刪除!.", SEVERE);
endif;
// 刪除程序文件夾中的快捷方式
if (DeleteFolderIcon (FOLDER_PROGRAMS, "My Demo in Programs") < 0) then
MessageBox ("安裝程序在刪除程序文件夾中的快捷方式的時(shí)候出錯(cuò),稍侯請(qǐng)自己刪除!.", SEVERE);
endif;
/*************** 結(jié)束 ***************/
好了,我們可以拿著這個(gè)安裝程序向老板領(lǐng)賞了。還不趕快制作一個(gè)具有專業(yè)級(jí)水平的應(yīng)用程序安裝盤來分發(fā)給我們的客戶。相信他們一定會(huì)瞪大眼睛驚嘆我們的軟件開發(fā)水平是一流的。廢話不說了,現(xiàn)在就開始行動(dòng)!
總結(jié)
至此,所有圖例的有關(guān)技術(shù)已經(jīng)全部講述完畢??傊?,InstallShield博大精深,我所敘述的只是一些皮毛而已,如果大家對(duì)她想更深入的了解還是請(qǐng)看她自帶的幫助文檔。
不過,最后我還是要多說一句,千萬不要忘了編寫一個(gè)詳細(xì),完整的用戶手冊。這可是用戶最需要的,但同時(shí)也是我們最懶得去做的一件事。

相關(guān)文章

最新評(píng)論