首先建一個Web應用程序的安裝項目
建好項目後在該安裝項目的文件系統中加入Web應用程序的所有文件,全選後拖到"Web應用程序文件夾"內即可,也可以在"Web應用程序文件夾"點擊右鍵在菜單中選擇添加文件
如果有多個Web應用程序需要放在同一個安裝包內安裝,可以在"目標計算機上的文件系統"上點右鍵添加"Web自定義文件夾",如圖中的WebControls
在Web文件夾的屬性裏,可以設置一下默認頁及虛擬目錄名稱,其他的屬性可以無視,使用默認值就可以了
到此,一個Web應用程序的安裝包就基本完成了,直接生成的安裝程序就可以將安裝到\Inetpub\wwwroot目錄下成爲一個虛擬站點了,如果你的站點沒有數據庫的話,基本可以打完收工了^_^
之後遇到的第一個問題就是如何安裝數據庫.在網上找了一些資料,雖然說的比較詳細,但都沒有圖例,習慣了傻瓜教程的我花了不少時間去摸索,下面就圖文說明一下
先設計用戶錄入SQL數據庫信息的界面,這個VS.NET有現成的界面,稍微修改一下即可,非常簡單,打開安裝包項目的用戶界面
在"啓動"項裏添加一個"文本框(A)"對話框
將"文本框(A)"移動到安裝流程中合適的位置,設置一下屬性,請注意,這裏的EditProperty的值是傳遞用戶輸入數據的關鍵字,必填
下面就進入重點了,這個流程的操作搞了半天才搞明白,在解決方案中再建一個類庫項目,名字叫DBInstall,在該項目創建一個繼承於System.Configuration.Install.Installer的類
暫時不寫代碼,將此類庫與安裝項目關聯起來先,在"Web應用程序文件夾"下的任意文件夾裏點擊右鍵添加一個"項目輸出"
默認會選中當前的DBInstall項目,不用改任何選項直接點確定,會在文件夾中新增一個"主輸出來自DBInstall(活動)"的文件項
接下來在項目自定義操作的"安裝"項上點右鍵添加自定義操作,選擇剛剛新增"主輸出來自DBInstall(活動)"的文件夾,選中確定添加到安裝項內
添加完畢後設置"主輸出來自DBInstall(活動)"的CustomActionData屬性的值爲 /dbname=[CUSTOMTEXTA1] /server=[CUSTOMTEXTA2] /user=[CUSTOMTEXTA3] /pwd=[CUSTOMTEXTA4] /targetdir="[TARGETDIR]\" ,通過該格式化字符串接收用戶輸入傳遞給安裝程序的自定義數據,前4個傳入值是"文本框(A)"中相關聯的TextBox的值,第5個參數"TARGETDIR"返回的是Web應用程序安裝路徑
現在,可以去寫安裝Sql數據庫的代碼,在繼承於System.Configuration.Install.Installer的InstallDb類中重載Install方法,在該方法內編寫安裝過程中需要執行的代碼
先編寫個執行SQL語句的方法,後面編寫安裝數據庫的代碼時需要用到,傳入的參數分別是 connStr - 數據庫鏈接字符串,DatabaseName - 鏈接的數據庫名稱,Sql - 待執行的SQL語句
2 SqlConnection conn = new SqlConnection(connStr);
3 SqlCommand cmd = new SqlCommand(Sql, conn);
4
5 conn.Open();
6 conn.ChangeDatabase(DatabaseName);
7 try {
8 cmd.ExecuteNonQuery();
9 }
10 finally {
11 conn.Close();
12 }
13 }
在研究過程中,我嘗試了3種安裝數據庫的方法,下面將一一講解一下
第一種方法是通過附加數據庫的方式來實現安裝數據庫,首先將需要安裝的初始化數據庫從Sql Server中分離,將該數據庫的mdf和ldf文件添加到"Web應用程序文件夾"中,這裏是放在DataBase文件夾中的,在Install方法中添加以下代碼
2 string strSql = "EXEC sp_attach_db @dbname = N'" + this.Context.Parameters["dbname"] + "',"
3 + "@filename1 = N'" + this.Context.Parameters["targetdir"] + "DataBase\\DemoData.mdf',"
4 + "@filename2 = N'" + this.Context.Parameters["targetdir"] + "DataBase\\DemoData_log.ldf'";
5 ExecuteSql(connStr, "master", strSql);
可以看到,通過this.Context.Parameters["KeyName"]的方法,可以獲取由應用程序傳遞的自定義數據,獲取數據庫的相關信息拼成鏈接字符串,再拼一個附加數據庫的SQL語句,用的是master庫中的存儲過程sp_attach_db,3個參數分別是數據庫的名稱,及mdf和ldf完整路徑,因此要拼完整具體目錄並加上文件名,這樣,執行一下這個Sql語句即能將數據庫附加到Sql Server,但是這樣做有個問題,卸載安裝時安裝程序會刪除mdf和ldf文件,如果數據庫在使用中,則卸載出錯,如果數據庫未使用,則被刪除,後果嚴重,因此,只能用腳本去安裝數據庫
第二種方法是從網上看來的,在進程中通過osql.exe去執行SQL腳本文件安裝數據庫
2 sqlProcess.StartInfo.FileName = "osql.exe";
3 sqlProcess.StartInfo.Arguments = string.Format(" -U {0} -P {1} -d {2} -i {3}/db.sql", this.Context.Parameters["user"], this.Context.Parameters["pwd"], this.Context.Parameters["dbname"], this.Context.Parameters["targetdir"]);
4 sqlProcess.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
5 sqlProcess.Start();
6 sqlProcess.WaitForExit(); //等待執行
此種方法需要開一個進程,性能比較高,並且將進程的WindowStyle設置爲Hidden,用戶就看不到執行時的Dos窗體了,最後,一定要加上等待執行完成的WaitForExit方法,否則,數據庫還未安裝完成時安裝程序很可能就已經完成安裝提示用戶可以退出了
第三種方法是直接用先前所寫的ExecuteSql方法執行安裝腳本中的Sql語句
2 ExecuteSql(connStr, "master", "CREATE DATABASE " + this.Context.Parameters["dbname"]);
3
4 StringBuilder sb = this.GetSqlFile("Demo.sql");
5 ExecuteSql(connStr, this.Context.Parameters["dbname"], sb.ToString());
6
7 sb = this.GetSqlFile("Demo_Data.sql");
8 ExecuteSql(connStr, this.Context.Parameters["dbname"], sb.ToString());
通過GetSqlFile方法獲得腳本中的Sql,這裏用了兩個腳本文件,一個是創建數據庫的,一個是創建默認數據的,兩個腳本文件是可以合併成一個文件的,執行一次即可
2 private StringBuilder GetSqlFile(string pFileName) {
3 StringBuilder sqlTemp = new StringBuilder();
4
5 sqlTemp.Append(File.ReadAllText(this.Context.Parameters["targetdir"] + "DataBase\\" + pFileName, System.Text.Encoding.GetEncoding("GB2312")));
6
7 return sqlTemp;
8 }
需要提醒的是,創建數據庫的腳本文件中,需要將"GO","SET ANSI_NULLS ON","SET QUOTED_IDENTIFIER ON"去掉,否則通過SqlCommand執行會出錯,另外,如果默認數據的Insert腳本中包含中文,讀取Sql語句時要加上System.Text.Encoding.GetEncoding("GB2312")這個參數,否則中文變亂碼,默認數據的Insert腳本可以在網上找到導出所有數據Insert語句的存儲過程
3種安裝數據庫的方法中後兩種比較實用,第一種方法雖然方便快捷,但是卸載時萬一將數據庫也誤卸載,那就損失慘重了
接下來說兩個小問題,安裝好了肯定要配置Web.Config中的數據庫鏈接字符串,網上有現成的修改App.Config和Web.Config的方法,和安裝數據庫時的方法一樣,拼好數據庫鏈接字符串,調用修改Web.Config的方法,通過鍵名找到相應的鍵,將鍵值改爲新的數據庫鏈接字符串即可
另一個問題是在不同系統環境下測試安裝包時發現的,如果系統中有.NET 1.1和.NET 2.0兩個環境,安裝的虛擬站點默認使用1.1的.NET版本,如果系統先安裝了.NET 2.0再安裝IIS,那默認網站的ASP.NET版本選項是空的,沒有選中2.0版本,因此安裝的虛擬目錄ASP.NET版本選項也是空的,問了不少網友,都說需要執行aspnet_regiis.exe -i去註冊2.0版本的.NET,但是如果安裝好了再讓用戶去做這些操作總覺得有些彆扭,看了一下aspnet_regiis.exe的參數說明,發現可以對某個虛擬站點進行.NET版本註冊,就寫下面這段代碼去註冊當天安裝的虛擬目錄
2
3 System.Diagnostics.Process process = new System.Diagnostics.Process();
4 process.StartInfo.FileName = path;
5 process.StartInfo.Arguments = "-s W3SVC/1/ROOT/" + "虛擬站點名稱";
6 process.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
7 process.Start();
8 process.WaitForExit();
第一行的代碼是獲取aspnet_regiis.exe的具體路徑,然後通過一個進程去執行註冊操作,這樣,即使出現前兩種情況,都不用擔心沒有將虛擬站點的ASP.NET版本註冊正確Web應用程序無法運行了
這兩部分代碼可以建一個像安裝數據庫一樣繼承於System.Configuration.Install.Installer的自定義操作來執行,不過,方便起見,直接放在InstallDB類中就可以了
安裝包的製作是件很複雜的事,通過這次經歷,只是學到了一點皮毛,在這裏班門弄斧一下,希望對需要的朋友有所幫助^_^