前言
前陣子做了一個有關Installshield的OA 打包安裝程序,用的版本Installshield 2010-Premier,具體功能的內容如下:
1、OA采用的是asp.net(C#)開發
2、動態發布到IIS虛擬目錄(采用自定義對話框)
3、附加,分離,刪除數據庫
4、動態修改web.config
5、完美卸載
6、更新包制作
【安裝】首先准備一個發布好的aspnet網站,然后在web.config插入標簽,在app_data文件夾放入數據庫文件。安裝的時候會自動把文件copy到目標機器,在使用dos命令將app_data里面的文件附加到數據庫,根據用戶填寫的數據庫信息替換web.config的標簽……
【更新】更新包的思路也很簡單,在安裝的時候會把用戶填寫的數據庫信息存到注冊表(數據庫服務器,用戶名,密碼,虛擬目錄,安裝路徑),用了這些信息,那么更新的時候直接把文件copy到用戶安裝時選擇的路徑就可以了,如果有數據庫相關的更新,則可以使用dos命令執行數據庫文件(.sql),如果有web.config的更新,則再一次動態替換web.config的標簽即可。
【卸載】網站的卸載就是刪除文件,分離和刪除數據庫,刪除注冊表相關鍵值,刪除虛擬目錄
接下來讓我們一步一步來實現,篇幅可能有點長,請大家 pay patience,Let’s go
一、新建項目
選擇All Types下面的InstallScript MSI Project,填寫產品名稱,保存路徑,點擊OK
點擊OK后出來這個界面Project Assistant 項目助手,點擊進去可看到有些簡單描述項目的選項
Installation Designer安裝設計,點擊進去可看到產品的信息,安裝腳本,安裝界面等
切換到Installation Designer可看到以上界面。
二、填寫產品信息
填寫產品的基本信息(包括產品名稱,安裝語言,產品的安裝版本,產品編碼……)
三、選擇文件源
選擇文件源,在DefaultComponents下面的files點擊右鍵,選擇Dynamic File Linking選擇文件源(將文件源填充到components,多個components組成一個features)
點擊 New Link彈出Dynamic File Link Settings對話框,點擊Browse選擇文件夾,然后點擊OK,在點擊左邊對話框的確定,則完成文件源的設置
定位到Setup Design選項,可看到右邊窗口有DefaultFeature和DefaultComponents
1個Feature(功能)可以拆分為多個Components(組件),1:N
1個Components可以綁定一個文件夾或者文件,1:N
在Defaultfeature右鍵選擇Associate Components,彈出Component的列表,選擇然后點擊OK按鈕則可以將該components添加到feature下面。
四、設置文件夾權限
功能Feature關聯完Component后則可以在Application Data下面的files and folders看到關聯過來的文件夾信息,可以對其進行局部調整。也可以對文件夾進行權限控制,權限設置如下:
選中文件夾,右鍵點擊Properties屬性,則彈出以下屬性窗口
點擊Permissions彈出以下界面
在空白處點擊右鍵選擇New,則彈出以下界面
設置文件夾的權限,點擊OK完成
五、Installshield Script
默認的腳本沒有任何東西,只有一句 #include "ifx.h",必須點擊右邊的安裝函數才出來腳本。
InstallScript腳本的語法類似於C,也類似於VBScript,可以調用VB的代碼。也可以調用dos命令,也可以調用exe。
選擇 Before Move Data 階段的函數 OnFirstUIBefore,可出來安裝過程中對話框的代碼,代碼如下:
NUMBER nResult, nSetupType, nvSize, nUser;
STRING szTitle, szMsg, szQuestion, svName, svCompany, szFile;
STRING szLicenseFile;
BOOL bCustom, bIgnore1, bIgnore2;
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));
// Added in InstallShield 15 - Show an appropriate error message if
// -removeonly is specified and the product is not installed.
if( REMOVEONLY ) then
Disable( DIALOGCACHE );
szMsg = SdLoadString( IDS_IFX_ERROR_PRODUCT_NOT_INSTALLED_UNINST );
SdSubstituteProductInfo( szMsg );
MessageBox( szMsg, SEVERE );
abort;
endif;
nSetupType = TYPICAL;
Dlg_SdWelcome:
szTitle = "";
szMsg = "";
nResult = SdWelcome(szTitle, szMsg);
if (nResult = BACK) goto Dlg_SdWelcome;
szTitle = "";
svName = "";
svCompany = "";
Dlg_SdRegisterUser:
szMsg = "";
szTitle = "";
nResult = SdRegisterUser( szTitle, szMsg, svName, svCompany );
if (nResult = BACK) goto Dlg_SdWelcome;
Dlg_SetupType:
szTitle = "";
szMsg = "";
nResult = SetupType2(szTitle, szMsg, "", nSetupType, 0);
if (nResult = BACK) then
goto Dlg_SdRegisterUser;
else
nSetupType = nResult;
if (nSetupType != CUSTOM) then
nvSize = 0;
FeatureCompareSizeRequired(MEDIA, INSTALLDIR, nvSize);
if (nvSize != 0) then
MessageBox(szSdStr_NotEnoughSpace, WARNING);
goto Dlg_SetupType;
endif;
bCustom = FALSE;
goto Dlg_SQL;
else
bCustom = TRUE;
endif;
endif;
Dlg_SdAskDestPath:
nResult = SdAskDestPath(szTitle, szMsg, INSTALLDIR, 0);
if (nResult = BACK) goto Dlg_SetupType;
Dlg_SdFeatureTree:
szTitle = "";
szMsg = "";
if (nSetupType = CUSTOM) then
nResult = SdFeatureTree(szTitle, szMsg, INSTALLDIR, "", 2);
if (nResult = BACK) goto Dlg_SdAskDestPath;
endif;
Dlg_SQL:
nResult = OnSQLLogin( nResult );
if( nResult = BACK ) then
if (!bCustom) then
goto Dlg_SetupType;
else
goto Dlg_SdFeatureTree;
endif;
endif;
Dlg_SdStartCopy:
szTitle = "";
szMsg = "";
nResult = SdStartCopy2( szTitle, szMsg );
if (nResult = BACK) then
goto Dlg_SQL;;
endif;
// Added in IS 2009 - Set appropriate StatusEx static text.
SetStatusExStaticText( SdLoadString( IDS_IFX_STATUSEX_STATICTEXT_FIRSTUI ) );
// setup default status
Enable(STATUSEX);
return 0;
end;
Dlg_SdWelcome: 歡迎對話框
Dlg_SdRegisterUser 注冊用戶對話框
Dlg_SetupType 安裝類型對話框
Dlg_SdAskDestPath 選擇安裝目錄對話框
Dlg_SdFeatureTree 功能樹對話框
Dlg_SQL sql相關對話框
Dlg_SdStartCopy 復制文件對話框
這幾個是系統默認的對話框,所有對話框的生命周期基於Setup.rul腳本,也就是說需要在Setup.Rul里面設置對話框的相關腳本信息和調用對話框的構造函數。
系統默認的對話框腳本都包含在#include "ifx.h"頭文件里面,如果是自定義的對話框則【后面會提到】需要引用相關對話框的腳本。
若要引用其他的對話框,則要從dialog source里面調出對話框函數
六、Dialog對話框
對話框選項位於User Interface(用戶體驗,簡稱UI)下面的Dialog(對話框)選項
鼠標懸停在對話框名稱,右鍵,選擇Edit,可看到對話框的相關信息(布局,控件,屬性……Control Identifier是唯一標識列),可以修改對話框的布局和信息。
Skin則是對話框的皮膚,選中皮膚,點擊Select應用該皮膚。
七、一個完整的ASP.NET打包程序
1、前言
在了解了Installshield 2010 的一些基本設置和熟悉操作界面后,給大家演示一個完整的ASP.NET打包程序,ASP.NET的安裝與部署比較簡單,主要是把網站發布到IIS,附加數據庫,配置數據庫信息(包括數據庫用戶,密碼,服務器),修改web.config配置文件。主要功能有:
● 手動選擇安裝目錄
● 創建和設置IIS虛擬目錄
● 動態附加分離數據庫
● 自動修改配置文件
● 完美卸載
2、創建IIS虛擬目錄
2.1、自定義創建虛擬目錄對話框
由於Installshield自身沒有操作IIS的功能,那么就要借助外部程序或者windowsAPI,用程序配置 IIS 所用到的“技術”無非是 ADSI 或者 WMI 提供的組件服務程序。可以通過 Windows Host Script 來執行 JScript 或者 VBScript 腳本,也可以在 VB/Delphi 這類快速開發工具開發程序來調用,甚至可以通過瀏覽器中運行的 JavaScript/JScript/VBScript 以及 IIS 運行的 ASP 來調用。因為支持 IDispatch 接口,所以可以后期綁定地通過 CreateObject 或者 GetObject 方式來獲取 ADSI/WMI 的特定接口。那么我們這里就簡單地利用adsi來操作IIS。
由於Installshield自身沒有創建虛擬目錄的窗口,那么我們就簡單的自己做一個自定義的窗口,窗口很簡單,就只有一個文本框,用於輸入虛擬目錄的名稱。制作過程如下:
首先先All Dialogs那里右鍵,彈出菜單,選擇New Dialog
新建對話框向導
對話框有多種類型:
Blank Dialog 空對話框,該對話框什么都沒有,連上一步,下一步的按鈕都沒有
NewScriptBasedDialog 普通基於腳本的對話框,帶基本按鈕
NewSkinnableDialog 帶皮膚功能的對話框,帶基本按鈕
如果彈出沖突頁面,直接點擊SkipAll就行了。
添加完皮膚對話框后,界面如上,現在就可以對對話框進行編輯,修改對話框標題,按鈕的文字,字體大小,擺置方式等。最重要的是甚至對話框的Resource identifier,這是對話框的唯一標識列。
那么現在對話框已經添加完成了,那么如何在安裝的過程中顯示該對話框呢?
每個對話框都有一個構造函數,那么只有調用該對話框的構造函數就行了,接下來請看怎么編寫對話框的構造函數(詳情按F1)。
在DefineDialog ( szDialogName, hInstance, szDLLName,nDialogID, szDialogID, nReserved, hwndOwner, lMsgLevel ); 這個函數里,最主要的參數就是第四個nDialogID(對話框ID),也就是對話框Resource identifier屬性的值。那么對話框構造函數就可以這樣寫:
hInstance = 0;
szDLLName = "";
nSdDialog = "13001"
szDialog = "";
hwndParent = 0;
nResult = DefineDialog (szDialogName, hInstance, szDLLName, nSdDialog, szDialog,
hwndParent, HWND_INSTALL,
DLG_MSG_STANDARD|DLG_CENTERED);
if ( nResult = DLG_ERR ) then
bDone = TRUE;
return - 1;
endif;
這里設置了一個名字為SelectVirDialog的對話框,對話框ID為13001,其他參數可以為空或為0。那么有了構造函數,那么在Setup.rul里面就可以調用構造函數,使用對話框了。
一般為了方便管理,每個對話框都會配置一個對話框的腳本。腳本里面也就是構造函數和點擊按鈕的業務處理
Dlg_SdSelectVirtual:
szTitle= "";
szMsg= "";
nResult=SdSelectVirtual(szTitle,szMsg);
if(nResult=BACK) then
goto Dlg_SdAskDestPath;
endif;
if(nResult=NEXT && !MAINTENANCE) then
goto Dlg_SQL;
endif;
SdSelectVirtual也就是一個構造函數,里面封裝了DefineDialog 函數和業務處理。返回的是按鈕ID,BACK和NEW都是枚舉值。
對話框其實處於一種死循環狀態,只靠goto語句來跳出循環。具體出來的對話框界面如下:
那么如果獲取用戶輸入的值呢?
跟對話框的原理一樣,每一個控件也是有一個唯一標識列的(Control Identifier)
設置控件的值CtrlSetText(szDialogName,1204,"A8");
獲取控件的值CtrlGetText(szDialogName,1204,svVituralDir);
1204是控件的Control Identifier
szDialogName是對話框的名稱,跟DefineDialog第一個參數相對應。
最后一個參數則是設置和獲取填充的值或變量。
bDone = FALSE;
// Loop until done.
while (!bDone)
// Display the dialog and return the next dialog event.
nId = WaitOnDialog( szDlg);
// Respond to the event.
switch(nId)
case DLG_INIT:
CtrlSetText(szDialogName, 1204, " A8 ");
// No initialization is required for this example.
case NEXT:
nId = NEXT;
bDone = TRUE;
CtrlGetText(szDialogName, 1204,svVituralDir);
// 將路徑寫到注冊表
nRootKey = HKEY_CURRENT_USER;
szKey = " Software\\A8 ";
szClass= "";
// 更換注冊表根目錄
if (RegDBSetDefaultRoot (nRootKey) < 0) then
MessageBox ( " First call to RegDBSetDefaultRoot failed. ", SEVERE);
endif;
// 創建注冊表項
if (RegDBKeyExist (szKey) < 0) then
if (RegDBCreateKeyEx (szKey, szClass) < 0) then
MessageBox ( " RegDBCreateKeyEx failed. ", SEVERE);
endif;
endif;
// 創建鍵值對[虛擬目錄,目標目錄]
RegDBSetKeyValueEx (szKey, " VirDir ", REGDB_STRING, svVituralDir,- 1);
RegDBSetKeyValueEx (szKey, " TargetDir ", REGDB_STRING, TARGETDIR,- 1);
nExists=CreateWebSite(svVituralDir);
if(nExists== 0) then
nId= 0;
bDone=FALSE;
else
nId=NEXT;
bDone=TRUE;
endif;
case BACK:
nId = BACK;
bDone = TRUE;
case DLG_ERR:
SdError( - 1, " MyDefineDialog " );
nId = - 1;
bDone = TRUE;
case DLG_CLOSE:
SdCloseDlg( hwndDlg, nId, bDone );
default:
if(SdIsStdButton( nId ) && SdDoStdButton( nId )) then
bDone = TRUE;
endif;
endswitch;
endwhile;
2.2、創建虛擬目錄(使用ADSI)
設置好界面,獲取到用戶輸入的虛擬目錄名稱,接下來就是創建虛擬目錄了。
第一步:獲取IIS的Default站點
set objW3SVC = CoGetObject("IIS://localhost/W3SVC/1/Root","");
第二步:創建虛擬目錄
set objVirDir=objW3SVC.Create("IISWebVirtualDir",virtrualDir);//virtrualDir是變量
第三步:設置虛擬目錄的屬性
objVirDir.Path = TARGETDIR;
objVirDir.AccessRead = TRUE;
objVirDir.AccessScript = TRUE;
objVirDir.AppCreate(TRUE);
objVirDir.SetInfo();
詳細代碼請參考SdSelectVirtual.rul的CreateWebSite函數
3、填寫數據庫信息
3.1、自定義數據庫對話框
數據庫的對話框也需要自定義,在上面已經介紹過自定義對話框的制作方法,數據庫對話框界面如下:
填寫服務器信息,默認是localhost或者.都可以
填寫用戶名,默認一般是sa
填寫密碼,默認是******
3.2、驗證數據庫信息
// Loop until done.
while (!bDone)
// Display the dialog and return the next dialog event.
nId = WaitOnDialog( szDlg);
// Respond to the event.
switch(nId)
case DLG_INIT:
CtrlSetText(szDialogName,REX_CTRL_ID_SERVER, " localhost ");
CtrlSetText(szDialogName,REX_CTRL_ID_USER, "");
CtrlSetText(szDialogName,REX_CTRL_ID_PWD, "");
// No initialization is required for this example.
case NEXT:
nId = NEXT;
bDone = TRUE;
CtrlGetText(szDialogName,REX_CTRL_ID_SERVER,svServer);
CtrlGetText(szDialogName,REX_CTRL_ID_USER,svUser);
CtrlGetText(szDialogName,REX_CTRL_ID_PWD,svPwd);
Server=svServer;
User=svUser;
Pwd=svPwd;
// 判斷數據庫鏈接是否成功(0代表鏈接失敗,1代表鏈接成功)
szWaitTxt= " 正在檢查數據庫用戶名和密碼 ";
SdShowMsg (szWaitTxt, TRUE);
Delay( 2);
SdShowMsg (szWaitTxt, FALSE);
if(DB_CheckConnection(Server, " SQL Server ",User,Pwd)!= 1) then
nId= 0;
bDone=FALSE;
MessageBox ( " 數據庫用戶名或者密碼錯誤,請重新輸入 ", WARNING);
CtrlSetText(szDialogName,REX_CTRL_ID_USER, "");
CtrlSetText(szDialogName,REX_CTRL_ID_PWD, "");
else
nId=NEXT;
bDone=TRUE;
// 將路徑寫到注冊表
nRootKey = HKEY_CURRENT_USER;
szKey = " Software\\A8 ";
// 更換注冊表根目錄
if (RegDBSetDefaultRoot (nRootKey) < 0) then
MessageBox ( " First call to RegDBSetDefaultRoot failed. ", SEVERE);
endif;
// 創建注冊表項
if (RegDBKeyExist (szKey) < 0) then
if (RegDBCreateKeyEx (szKey, szClass) < 0) then
MessageBox ( " RegDBCreateKeyEx failed. ", SEVERE);
endif;
endif;
// 添加到注冊表
RegDBSetKeyValueEx (szKey, " Server ", REGDB_STRING, Server,- 1);
RegDBSetKeyValueEx (szKey, " User ", REGDB_STRING, User,- 1);
RegDBSetKeyValueEx (szKey, " Pwd ", REGDB_STRING, Pwd,- 1);
endif;
case BACK:
nId = BACK;
bDone = TRUE;
case DLG_ERR:
SdError( - 1, " MyDefineDialog " );
nId = - 1;
bDone = TRUE;
case DLG_CLOSE:
SdCloseDlg( hwndDlg, nId, bDone );
default:
if(SdIsStdButton( nId ) && SdDoStdButton( nId )) then
bDone = TRUE;
endif;
endswitch;
endwhile;
DB_CheckConnection 這個函數用於驗證當前用戶輸入的數據庫信息是否正確,有關數據庫的相關操作位於database.rul文件。
如果數據庫的信息填寫無誤,那么把數據庫信息寫到注冊表,方便以后升級使用。
4、附加數據庫
在執行復制文件到目標機器后,點擊Finish(完成)按鈕會觸發函數onend
// OnEnd
//
// The OnEnd event is called at the end of the setup. This event is not
// called if the setup is aborted.
// ---------------------------------------------------------------------------
function OnEnd()
begin
if(!MAINTENANCE)then
// ConfigurateSql();
CreateDataBase(Server,User,Pwd); // Server,User,Pwd為SdCreateSql.rul的全局變量
endif;
end;
Server,User,Pwd都是全局變量,把變量定義到最頂部跟#include同級
#include " database.rul "
#define REX_DIALOG_ID 13003
#define REX_CTRL_ID_SERVER 1209 // 服務器
#define REX_CTRL_ID_USER 1207 // 用戶名
#define REX_CTRL_ID_PWD 1208 // 密碼
export prototype SdCreateSql( string, string); // 構造函數
// prototype CreateDataBase(STRING,STRING,string); // 創建數據庫
prototype AlterConfigure( string); // 修改web.config
string Server,User,Pwd; //全局變量
附加數據庫是調用了dos命令的osql.exe,代碼如下:
function CreateDataBase(svSQLsvr,svSQLusr,svSQLpwd)
STRING szCmdLine,szWaitTxt,szCommandLine;
begin
// A8數據庫
szWaitTxt= " 正在創建A8數據庫. ";
SdShowMsg (szWaitTxt, TRUE);
Delay( 2);
szCmdLine = " /U "+svSQLusr+ " /P "+svSQLpwd+ " /S "+svSQLsvr+ " /Q \"EXEC sp_attach_db @dbname = N'A8',@filename1 = N' "+TARGETDIR ^ " App_Data\\A8.mdf',@filename2 = N' "+TARGETDIR ^ " App_Data\\A8_log.ldf'\" ";
if (LaunchAppAndWait( " osql.exe ", szCmdLine,LAAW_OPTION_NOWAIT | LAAW_OPTION_HIDDEN) < 0) then
MessageBox ( " 數據庫創建失敗!請確您的系統中已安裝 Microsoft SQL Server 2000. 如仍無法解決,請聯系系統供應商! ",SEVERE);
endif;
SdShowMsg (szWaitTxt,FALSE);
szWaitTxt= " 正在優化系統數據庫. ";
SdShowMsg (szWaitTxt, TRUE);
Delay( 2);
szCmdLine = " /U "+svSQLusr+ " /P "+svSQLpwd+ " /S "+svSQLsvr+ " /Q \"use A8 ; exec sp_updatestats\" ";
if (LaunchAppAndWait( " osql.exe ", szCmdLine,LAAW_OPTION_NOWAIT | LAAW_OPTION_HIDDEN) < 0) then
MessageBox ( " 數據庫優化失敗!您可以在 sql查詢分析器中執行 use dlbj ; exec sp_updatestats 完成! ",SEVERE);
endif;
SdShowMsg (szWaitTxt,FALSE);
// 打開瀏覽器瀏覽制定的網頁
szCommandLine = ProgramFilesFolder ^ " Internet Explorer\\iexplore.exe ";
LaunchAppAndWait(szCommandLine, " http://localhost/ "+svVituralDir+ " /login/login.aspx ", NOWAIT);
// 修改配置文件
ConfigurateSql();
end;
在這里使用了LaunchAppAndWait調用exe文件,詳情請按F1
修改Web.Config文件也是在文件拷貝到目標機器的完成階段實現。
第一步:定標簽
在Web.Config文件里為每一個要替換的節點定下一個注釋標簽
<connectionStrings>
<!--#constring1#-->
<add name="abc" connectionString="database=abc;server=.;uid=sa;pwd=123" providerName="System.Data.SqlClient"/>
</connectionStrings>
<!--#constring1#-->則是一個注釋標簽
第二步:定位行數
根據標簽就可以找到該標簽下面那一個節點,代碼看GetLineNum函數
function NUMBER GetLineNum(szFileName,szSearchStr,isContinue)
string svReturnLine;
NUMBER nvLineNumber,nvResult;
begin
nvResult = FileGrep (szFileName, szSearchStr, svReturnLine, nvLineNumber,isContinue);
switch(nvResult)
case FILE_NOT_FOUND:
// Report error; then abort.
MessageBox( szFileName + " not found. ", WARNING);
abort;
case FILE_LINE_LENGTH:
// Report error; then abort.
MessageBox (szFileName + " lines too long. ", WARNING);
abort;
case OTHER_FAILURE:
// Report error; then abort.
MessageBox (szFileName + " Unknown failure on call to FileGrep. ", WARNING);
abort;
endswitch;
return (nvLineNumber+ 1);
end ;
第三步:替換該行數據
使用FileInsertLine函數可以替換文件中的某一行。
nvLineNum=GetLineNum(ConFullDir,sConTag1,CONTINUE);
if(FileInsertLine(ConFullDir,ConString1,nvLineNum,REPLACE)< 0) then
MessageBox ( " FileInsertLine failed. ", SEVERE);
endif;
6、完美卸載
安裝過程已經完成,接下來看如何完美卸載程序(刪除文件,分離數據庫,刪除虛擬目錄)
選擇Installscript,找到你要卸載的Feature,默認是DefaultFeature,選擇卸載事件,UnInstalling(卸載前)和UnInstalled(卸載后)
第一步:分離數據庫
因為卸載界面已經脫離了安裝的生命周期,那么所有變量都被回收了,要獲取數據庫信息只能從注冊表獲取(安裝的時候已寫進了注冊表)
if (RegDBSetDefaultRoot (nRootKey) < 0) then
MessageBox ( " First call to RegDBSetDefaultRoot failed. ", INFORMATION);
endif;
// 從注冊表取數據庫和虛擬目錄相關信息
RgVirDir=GetReg( " VirDir ");
RgServer=GetReg( " Server ");
RgUser=GetReg( " User ");
RgPwd=GetReg( " Pwd ");
// 分離A8數據庫
szWaitTxt= " 正在分離A8數據庫 ";
SdShowMsg (szWaitTxt, TRUE);
Delay( 2);
szCmdLine = " /U "+RgUser+ " /P "+RgPwd+ " /S "+RgServer+ " /Q \"EXEC sp_detach_db 'A8' ";
if( LaunchAppAndWait( " osql.exe ", szCmdLine,LAAW_OPTION_NOWAIT | LAAW_OPTION_HIDDEN) < 0) then
MessageBox ( " 數據庫分離失敗!請確您的系統中已安裝 Microsoft SQL Server 2000. 如仍無法解決,請聯系系統供應商! ",SEVERE);
endif;
SdShowMsg (szWaitTxt, FALSE);
GetReg是一個自定義函數,參數則是注冊表的鍵名
分離數據庫還是使用dos命令下的osql.exe
刪除數據庫文件只能先分離,不然會有數據庫質疑的字樣
第二步:刪除虛擬目錄
set objW3SVC = CoGetObject( " IIS://localhost/W3SVC/1/Root ", ""); // 獲取Default站點
if(IsObject(objW3SVC)) then
if(IsObject( CoGetObject( " IIS://localhost/W3SVC/1/Root/ "+RgVirDir+ "", ""))) then
szWaitTxt= " 正在刪除 "+RgVirDir+ " 虛擬目錄 ";
Delay( 2);
SdShowMsg (szWaitTxt, TRUE);
objW3SVC.Delete( " IIsWebVirtualDir ",RgVirDir) ;
SdShowMsg (szWaitTxt, FALSE);
endif;
endif;
刪除虛擬目錄一樣使用了ADSI
第三步:停止數據庫服務和刪除注冊表鍵值
szCmdLine = " stop SQLSERVERAGENT ";
if(LaunchAppAndWait( " sc ", szCmdLine,LAAW_OPTION_NOWAIT | LAAW_OPTION_HIDDEN)< 0) then
MessageBox ( " 無法停止數據庫服務--SQLSERVERAGENT,請手動關閉該服務 ",SEVERE);
endif;
szCmdLine= " stop MSSQLSERVER ";
if(LaunchAppAndWait( " sc ", szCmdLine,LAAW_OPTION_NOWAIT | LAAW_OPTION_HIDDEN) < 0) then
MessageBox ( " 無法停止數據庫服務--MSSQLSERVER,請手動關閉該服務 ",SEVERE);
endif;
// 刪除完刪除注冊表
DelReg(KEY);
DelReg是自定義函數,參數是注冊表的鍵
第四步:刪除文件夾和啟動數據庫服務(在UnInstalled卸載后觸發)
// The UnInstalled event is sent after the feature DefaultFeature
// is uninstalled.
// sented after delete defaultFeature
// ---------------------------------------------------------------------------
export prototype DefaultFeature_UnInstalled();
function DefaultFeature_UnInstalled()
string szCmdLine;
begin
// 刪除后重新啟動數據庫服務--MSSQLSERVER
szCmdLine= " start MSSQLSERVER ";
if(LaunchAppAndWait( " sc ", szCmdLine,LAAW_OPTION_NOWAIT | LAAW_OPTION_HIDDEN) < 0) then
MessageBox ( " 無法啟動數據庫服務--MSSQLSERVER,請手動啟動該服務 ",SEVERE);
endif;
// 可能刪除不干凈,手動執行刪除文件夾
if(ExistsDir(TARGETDIR)=EXISTS ) then
if(DeleteDir(TARGETDIR,ALLCONTENTS) < 0) then
MessageBox( " 刪除失敗 ",SEVERE) ;
endif;
endif;
end;
啟動數據庫服務,刪除文件夾。
整個卸載過程完成。
八、更新包制作
1、前言
更新包也是一個獨立的InstallScript MSI Project,只不過相比於安裝包少了一些步驟,更新包的原理就是從注冊表讀出安裝時寫進的信息,如:數據庫服務器,用戶名,密碼,虛擬目錄,安裝路徑。界面略……
直接跳過選擇安裝目錄那個對話框,因為獲取了注冊表的那個安裝路徑了。代碼如下:
szTitle = "";
szMsg = "";
nResult = SdStartCopy2( szTitle, szMsg );
if (nResult = BACK) then
goto Dlg_SQL;;
endif;
// 獲取注冊表的目標路徑
TARGETDIR= GetReg( " TargetDir ");
// Added in IS 2009 - Set appropriate StatusEx static text.
SetStatusExStaticText( SdLoadString( IDS_IFX_STATUSEX_STATICTEXT_FIRSTUI ) );
// setup default status
Enable(STATUSEX);
return 0;
end;
2、選擇更新文件
方法跟安裝的時候是一樣的
3、修改Product Code,每次更新都要換一個Code,要不會出現(修復,卸載,重裝的操作界面)
4、運行sql語句
假如有更新sql語句,將需要運行的sql語句整理成一個文件
// OnEnd
//
// The OnEnd event is called at the end of the setup. This event is not
// called if the setup is aborted.
// ---------------------------------------------------------------------------
function OnEnd()
STRING szKey, szClass, szMsg, szTitle,szCmdLine,sqlRoot;
string targetDir,server,user,pwd;
NUMBER nRootKey;
begin
if(!MAINTENANCE)then
targetDir= GetReg( " TargetDir ");
server= GetReg( " Server ");
user= GetReg( " User ");
pwd= GetReg( " Pwd ");
sqlRoot= targetDir+ " sqlFile.sql " ;
LongPathToQuote(sqlRoot ,TRUE);
if(Is(FILE_EXISTS,sqlRoot)) then
szCmdLine = " /U "+user+ " /P "+pwd+ " /S "+server+ " /i "+sqlRoot+ "";
if (LaunchAppAndWait( " osql.exe ", szCmdLine,LAAW_OPTION_NOWAIT | LAAW_OPTION_HIDDEN) < 0) then
MessageBox ( " 運行sql更新文件時失敗,請聯系供銷商! ",SEVERE);
endif;
else
MessageBox ( " 找不到更新的sql文件,請聯系供銷商! ",SEVERE);
endif;
endif;
end;
執行更新的sql語句也是調用dos的osql.exe文件
5、屏蔽控制面板里添加刪除程序的那個安裝信息
九、結束語
首先感謝Installshield技術交流群(158107742)的群主海洋女神,Kevin,單車,棕橙藍綠……還有其他群里的朋友們。排名不分前后
如果有看不懂或者不明白的可以給我留言或者加qq群跟大家交流交流,如果想了解更專業的Installshield技術,可以閱讀以下的博客:
1.論壇http://www.appinstall.cn/
2.入門http://home.cnblogs.com/Cindy_weiwei
3.提高http://home.cnblogs.com/installshield
附:由於部分資源文件涉及公司機密,僅能提供自定義對話框和數據庫操作的腳本資源:/Files/magicchaiy/腳本.rar
2012年3月30日15:34:08