web項目製作成安裝包是為了方便發佈到伺服器上,本文主要講了安裝包製作,IIS部署,資料庫安裝,卸載時刪除IIS網站和資料庫 博文參考鏈接:http://www.cnblogs.com/huxj/archive/2010/09/10/1823637.html 下麵是本人通過網上資料和自己的思考總結進 ...
web項目製作成安裝包是為了方便發佈到伺服器上,本文主要講了安裝包製作,IIS部署,資料庫安裝,卸載時刪除IIS網站和資料庫
博文參考鏈接:http://www.cnblogs.com/huxj/archive/2010/09/10/1823637.html
下麵是本人通過網上資料和自己的思考總結進行補充,希望能對大家又所幫助。
首先我們需要一個已經發佈的網站
一、安裝包製作
打開網站
然後右鍵解決方案》添加》新建項目》其他項目類型》安裝和部署》Visual Studio Installer 》安裝項目
在web項目里新建一個安裝項目,如圖:
在新建的安裝項目,右鍵安裝項目》添加》項目輸出,如圖:
選擇項目輸出,選擇要操作的項目,如圖:
示例項目是一個web網站,所以只有一個內容文件輸出選項,選中內容文件點擊確定
如果示例項目是一個Web項目,則選擇主輸出,如下圖:
現在我們來製作安裝包的安裝界面,如圖選擇用戶界面:
右鍵啟動,添加對話框,如圖:
這裡可以根據安裝項目的需要來選擇設置。
這裡我們選擇文本框(A)、文本框(B)、許可協議
拖動對話框進行排序——對話框的排序代表著安裝時界面順序。
然後我們在文件系統》應用程式文件夾,右邊空白處右鍵》添加》文件,添加license.rtf文件 ,如圖:
現在我們回到用戶界面,選擇用戶協議對話框-屬性
可以看到LicenseFile沒有值,將剛添加進的license.rtf文件添加進去
選擇應用程式文件夾
由於在安裝過程也需要設置資料庫,所以我們還需要讓安裝用戶在安裝過程中輸入資料庫伺服器信息,選擇對話框(A)-屬性,設置如圖:
這裡我們只需要伺服器、賬號、密碼,所以Edit4Visible設為false.
由於在安裝過程中也需要設置IIS,所以還需要讓安裝用戶在安裝過程中輸入網站配置,選擇對話框(B)-屬性,設置如圖:
Value中的值都是為預設值
由於我們需要配置資料庫和iis,所以我們需要在新建兩個類庫(upLibrary1和unLibrary1),各自添加一個安裝程式類(添加的安裝程式類是一個繼承installer的類),如圖:
其中upLibrary1類庫是安裝,unLibrary1類庫是卸載。
現在我們在安裝項目Setup添加這兩個類庫,右鍵》添加》項目輸出》選擇upLibrary1類庫和unLibrary1類庫》選擇主輸出
添加後
然後右鍵安裝項目》自定義操作》右鍵安裝》添加自定義操作》應用程式文件夾
選擇主輸出來自upLibrary1(活動)
卸載中選擇主輸出來自unLibrary1(活動)
接下來我們需要在安裝過程傳遞輸入的數據傳遞這個項目中,選擇主輸出來自upLibrary1(活動),右鍵屬性,如圖:
屬性框中的CustomActionData就是指定要傳遞到安裝程式的自定義數據。
/server="'[EDITA1]'" /user="'[EDITA2]'" /pwd="'[EDITA3]'" /iis="[IISSERVER]" /ip="[IP]" /port="[PORT]" /ISNAME="[ISNAME]" /targetdir="[TARGETDIR]\"
/targetdir="[TARGETDIR]\"中的“\”記得不要丟了
現在我們回到upLibrary1安裝程式類:
我們先講upLibrary1類庫,先不管unLibrary1類庫
打開upInstaller1類是一個設計視圖,點擊 單擊此處切換到代碼視圖
在安裝程式類里我們可以寫安裝過程中的處理事件,比如附加資料庫,將網站發佈到iis上。
首先我們先從寫Install方法:
public override void Install(IDictionary stateSaver){ //這裡面就是我們的主要代碼區 }
在Install方法中我們可以接收安裝過程中輸出的數據信息,如下:
代碼塊:
安裝:
裡面包含資料庫的附加、連接iis伺服器、判斷網站是否存在、添加網站
1 using System; 2 using System.Collections; 3 using System.Collections.Generic; 4 using System.ComponentModel; 5 using System.Configuration.Install; 6 using System.Linq; 7 using System.Data.SqlClient; 8 using System.Management; 9 using System.IO; 10 using System.Security.AccessControl; 11 using System.DirectoryServices; 12 13 14 namespace upLibrary1 15 { 16 [RunInstaller(true)] 17 public partial class upInstaller1 : System.Configuration.Install.Installer 18 { 19 public upInstaller1() 20 { 21 InitializeComponent(); 22 } 23 24 string iis = ""; 25 string port = ""; 26 private string _target; 27 private string ISNAME; 28 private string targetdir; //安裝地址 29 private DirectoryEntry _iisServer; 30 private ManagementScope _scope; 31 private ConnectionOptions _connection; 32 33 public override void Install(IDictionary stateSaver) 34 { 35 36 base.Install(stateSaver); 37 string databaseServer = Context.Parameters["server"].ToString(); //資料庫伺服器 38 //string databasename = Context.Parameters["dbname"].ToString(); 39 string userName = Context.Parameters["user"].ToString(); //賬號 40 string userPass = Context.Parameters["pwd"].ToString(); //密碼 41 string targetdir = Context.Parameters["targetdir"].ToString(); //安裝地址 42 iis = this.Context.Parameters["iis"].ToString(); //伺服器 43 string ip = this.Context.Parameters["ip"].ToString(); //ip 44 port = this.Context.Parameters["port"].ToString(); //埠 45 ISNAME = this.Context.Parameters["ISNAME"].ToString(); //網站名 46 47 string serverID = "66"; //和iis上的網站ID不可重覆 48 try 49 { 50 //System.Diagnostics.Debugger.Launch(); //調試代碼 51 Connect(); 52 string serverComment = ISNAME; 53 string defaultVrootPath = this.Context.Parameters["targetdir"]; 54 if (defaultVrootPath.EndsWith(@"\")) 55 { 56 defaultVrootPath = defaultVrootPath.Substring(0, defaultVrootPath.Length - 1); 57 } 58 string HostName = ""; 59 string IP = ip; 60 string Port = port; 61 string sReturn = CreateWebSite(serverID, serverComment, defaultVrootPath, HostName, IP, Port); 62 63 //給文件添加"Authenticated Users,Everyone,Users"用戶組的完全控制許可權 64 if (File.Exists(Context.Parameters["targetdir"].ToString() + "App_Data\\jiaowuDB.mdf")) 65 { 66 FileInfo fi = new FileInfo(Context.Parameters["targetdir"].ToString() + "App_Data\\jiaowuDB.mdf"); 67 System.Security.AccessControl.FileSecurity fileSecurity = fi.GetAccessControl(); 68 fileSecurity.AddAccessRule(new FileSystemAccessRule("Everyone", FileSystemRights.FullControl, AccessControlType.Allow)); 69 fileSecurity.AddAccessRule(new FileSystemAccessRule("Authenticated Users", FileSystemRights.FullControl, AccessControlType.Allow)); 70 fileSecurity.AddAccessRule(new FileSystemAccessRule("Users", FileSystemRights.FullControl, AccessControlType.Allow)); 71 fi.SetAccessControl(fileSecurity); 72 FileInfo fi1 = new FileInfo(Context.Parameters["targetdir"].ToString() + "App_Data\\jiaowuDB.ldf"); 73 System.Security.AccessControl.FileSecurity fileSecurity1 = fi1.GetAccessControl(); 74 fileSecurity1.AddAccessRule(new FileSystemAccessRule("Everyone", FileSystemRights.FullControl, AccessControlType.Allow)); 75 fileSecurity1.AddAccessRule(new FileSystemAccessRule("Authenticated Users", FileSystemRights.FullControl, AccessControlType.Allow)); 76 fileSecurity1.AddAccessRule(new FileSystemAccessRule("Users", FileSystemRights.FullControl, AccessControlType.Allow)); 77 fi1.SetAccessControl(fileSecurity1); 78 } 79 80 string connectionString = GetConnectionString(null); 81 //保存數據連接詞,為卸載做準備 82 File.WriteAllText(Path.Combine(targetdir + "App_Data\\", "log.txt"), connectionString); 83 try 84 { 85 using (SqlConnection connection = new SqlConnection(connectionString)) 86 { 87 connection.Open(); 88 //使用資料庫文件創建資料庫,所以添加的網站項目中需要有App_Data文件夾和資料庫文件(jiaowuDB.mdf)和日誌文件(jiaowuDB.ldf) 89 string sql = "sp_attach_db 'jiaowuDB','" + Context.Parameters["targetdir"].ToString() + "App_Data\\jiaowuDB.mdf','" 90 + Context.Parameters["targetdir"].ToString() + "App_Data\\jiaowuDB.ldf'"; 91 ExecuteSQL(connection, sql); 92 connection.Close(); 93 //修改config文件連接詞 94 string webconfigpath = Path.Combine(this.Context.Parameters["targetdir"].ToString(), "web.config"); 95 string webcofnigstring = File.ReadAllText(webconfigpath).Replace("#constring#", GetConnectionString("jiaowuDB")); 96 File.WriteAllText(webconfigpath, webcofnigstring); 97 98 } 99 } 100 catch (Exception e) 101 { 102 throw new Exception(e.Message); 103 } 104 } 105 catch (Exception ex) 106 { 107 base.Rollback(stateSaver); 108 109 throw new Exception(ex.Message); 110 } 111 } 112 113 #region Connect 連接IIS伺服器 114 public bool Connect() 115 { 116 117 if (iis == null) 118 return false; 119 try 120 { 121 _iisServer = new DirectoryEntry("IIS://" + iis + "/W3SVC/1"); 122 _target = iis; 123 _connection = new ConnectionOptions(); 124 _scope = new ManagementScope(@"//" + iis + @"/root/MicrosoftIISV2", _connection); 125 _scope.Connect(); 126 } 127 catch 128 { 129 130 return false; 131 } 132 return IsConnected(); 133 } 134 135 public bool IsConnected() 136 { 137 if (_target == null || _connection == null || _scope == null) return false; 138 return _scope.IsConnected; 139 } 140 #endregion 141 142 #region CreateWebsite 添加網站 143 public string CreateWebSite(string serverID, string serverComment, string defaultVrootPath, string HostName, string IP, string Port) 144 { 145 try 146 { 147 ManagementObject oW3SVC = new ManagementObject(_scope, new ManagementPath(@"IIsWebService='W3SVC'"), null); 148 149 if (IsWebSiteExists(serverID)) 150 { 151 throw new Exception("伺服器上已存在" + ISNAME); 152 } 153 154 ManagementBaseObject inputParameters = oW3SVC.GetMethodParameters("CreateNewSite"); 155 ManagementBaseObject[] serverBinding = new ManagementBaseObject[1]; 156 serverBinding[0] = CreateServerBinding(HostName, IP, Port); 157 inputParameters["ServerComment"] = serverComment; 158 inputParameters["ServerBindings"] = serverBinding; 159 inputParameters["PathOfRootVirtualDir"] = defaultVrootPath; 160 inputParameters["ServerId"] = serverID; 161 162 ManagementBaseObject outParameter = null; 163 outParameter = oW3SVC.InvokeMethod("CreateNewSite", inputParameters, null); 164 165 // 啟動網站 166 //string serverName = "W3SVC/" + serverID; 167 //ManagementObject webSite = new ManagementObject(_scope, new ManagementPath(@"IIsWebServer='" + serverName + "'"), null); 168 //webSite.InvokeMethod("Start", new object[] {}); 169 170 return (string)outParameter.Properties["ReturnValue"].Value; 171 } 172 catch (Exception ex) 173 { 174 throw new Exception(ex.Message); 175 } 176 } 177 178 public ManagementObject CreateServerBinding(string HostName, string IP, string Port) 179 { 180 try 181 { 182 ManagementClass classBinding = new ManagementClass(_scope, new ManagementPath("ServerBinding"), null); 183 ManagementObject serverBinding = classBinding.CreateInstance(); 184 serverBinding.Properties["Hostname"].Value = HostName; 185 serverBinding.Properties["IP"].Value = IP; 186 serverBinding.Properties["Port"].Value = Port; 187 serverBinding.Put(); 188 return serverBinding; 189 } 190 catch 191 { 192 return null; 193 } 194 } 195 #endregion 196 197 #region IsWebSiteExists 判斷網站是否已經存在 198 public bool IsWebSiteExists(string serverID) 199 { 200 try 201 { 202 string siteName = "W3SVC/" + serverID; 203 ManagementObjectSearcher searcher = new ManagementObjectSearcher(_scope, new ObjectQuery("SELECT * FROM IIsWebServer"), null); 204 205 ManagementObjectCollection webSites = searcher.Get(); 206 foreach (ManagementObject webSite in webSites) 207 { 208 if ((string)webSite.Properties["Name"].Value == siteName) 209 return true; 210 } 211 212 return false; 213 } 214 catch 215 { 216 return false; 217 } 218 } 219 #endregion 220 221 /// <summary> 222 /// 執行sql語句 223 /// </summary> 224 /// <param name="connection"></param> 225 /// <param name="sql"></param> 226 void ExecuteSQL(SqlConnection connection, string sql) 227 { 228 SqlCommand cmd = new SqlCommand(sql, connection); 229 cmd.ExecuteNonQuery(); 230 } 231 232 233 /// <summary> 234 /// 獲取資料庫登錄連接字元串 235 /// </summary> 236 /// <param name="databasename">資料庫名稱</param> 237 /// <returns></returns> 238 private string GetConnectionString(string databasename) 239 { 240 return "server=" + Context.Parameters["server"].ToString() + ";database=" + (string.IsNullOrEmpty(databasename) ? "master" : databasename) + ";User ID=" + Context.Parameters["user"].ToString() + ";Password=" + Context.Parameters["pwd"].ToString(); 241 } 242 243 } 244 }View Code
Web項目的資料庫連接都是在Web.config中的,所以安裝過程還要修改Web.config的資料庫連接,這裡使用簡單的替換。
如下:
1 //修改config文件連接詞 2 string webconfigpath = Path.Combine(this.Context.Parameters["targetdir"].ToString(), "web.config"); 3 string webcofnigstring = File.ReadAllText(webconfigpath).Replace("#constring#", GetConnectionString("jiaowuDB")); 4 File.WriteAllText(webconfigpath, webcofnigstring); 5 6 //Web 項目中WebConfig中配置
7 <add name="ConnectionString" connectionString="#constring#" providerName="System.Data.SqlClient" /> 8 //就是替換#constring#為安裝過程中生成的新的鏈接字元串。
當然建站不止只有這些,還有新建應用程式池,大家可以去找找資料進行補充
安裝就到這兒了,現在來看看卸載。
卸載:
首先右鍵安裝項目》自定義操作》右鍵卸載》添加自定義操作》應用程式文件夾
選擇主輸出來自unLibrary1(活動)
不過我們這裡並不需要設置CustomActionData值,直接寫代碼
因為一般卸載的時候都不會去設置什麼數據
在示例中的做法在安裝的時候是沒有問題的,在卸載或者修複的時候,就會有問題了,卸載的時候我們需要刪除資料庫文件,那麼我就需要連接資料庫了
1 /// <summary> 2 /// 獲取資料庫登錄連接字元串 3 /// </summary> 4 /// <param name="databasename">資料庫名稱</param> 5 /// <returns></returns> 6 private string GetConnectionString(string databasename) 7 { 8 return "server=" + Context.Parameters["server"].ToString() + ";database=" + (string.IsNullOrEmpty(databasename) ? "master" : databasename) + ";User ID=" + Context.Parameters["user"].ToString() + ";Password=" + Context.Parameters["pwd"].ToString(); 9 }
這裡是無法獲取正確的鏈接字元串,Context.Parameters["server"] 這些都已經不存在了,所以要想在卸載和修複的時候都可以用,則需要在安裝的時候保存連接字元串。
保存的位置和方式可根據自己的喜好存儲,畢竟連接字元串不是機密,示例中我們是保存在App_Date中的
1 string connectionString = GetConnectionString(null); 2 //保存數據連接詞,為卸載做準備 3 File.WriteAllText(Path.Combine(targetdir + "App_Data\\", "log.txt"), connectionString);
當然我們也可以在安裝保存的時候對連接字元串進行加密,在卸載中進行解密。
1 //判斷文件是不是存在 2 string webconfigpath = ""; 3 if (File.Exists(s + "App_Data\\log.txt")) 4 {
//讀取文件中的連接字元串 5 webconfigpath = Path.Combine(s + "App_Data\\", "log.txt"); 6 7 string connectionString = File.ReadAllText(webconfigpath); 8 try 9 { 10 using (SqlConnection connection = new SqlConnection(connectionString)) 11 { 12 connection.Open(); 13 string sql = " if exists(select * from sysdatabases where name='jiaowuDB' )begin alter database jiaowuDB set single_user with rollback immediate drop database jiaowuDB end "; 14 ExecuteSQL(connection, sql); 15 connection.Close(); 16 } 17 File.Delete(s + "App_Data\\log.txt"); 18 } 19 catch (Exception es) 20 { 21 MessageBox.Show("刪除數據失敗,請手動刪除!\n" + es.Message, "出錯啦!"); 22 } 23 }
unLibrary1類代碼:
1 using System; 2 using System.Collections; 3 using System.Collections.Generic; 4 using System.ComponentModel; 5 using System.Configuration.Install; 6 using System.Linq; 7 using System.Management; 8 using System.Data.SqlClient; 9 using System.IO; 10 using System.DirectoryServices; 11 using System.Windows.Forms; 12 13 14 namespace unLibrary1 15 { 16