C# Web項目製作安裝包

来源:http://www.cnblogs.com/fish520/archive/2016/09/22/5882450.html
-Advertisement-
Play Games

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項目,則選擇主輸出,如下圖:

image

 

現在我們來製作安裝包的安裝界面,如圖選擇用戶界面:

右鍵啟動,添加對話框,如圖:

這裡可以根據安裝項目的需要來選擇設置。

這裡我們選擇文本框(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
              
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 與asp.net 打交道很多年,如今天微軟的優秀框架越來越多,其中微軟在基於mvc的思想架構,也推出了自己的一套asp.net mvc 框架,如果你親身體驗過它,會情不自禁的說‘漂亮’。回過頭來,‘漂亮’終歸有個好的思想,其中類似於AOP的思想,就在其中體現的淋漓盡致,今天本文主要討論的是基於AOP ...
  • 記得上高中時,給人當會計,幫忙結算月度工資;用的就是帶語音功能的計算器! 當時用起來倍兒爽,於是速度加倍,效率加速;結果讓老闆賠了不少錢! 就是因為這,我才對語音計算器有了深刻印象!可能是這貨坑了我!哼~! 好吧,閑言少敘,直入正題吧! 最近在做一個項目,有個簡單的功能,就是將文本轉換成語音。 研究 ...
  • 首先來講講TcpTrace實現的基本原理。說簡單點,TcpTracer就是一個監聽/轉發器(Listening/Forwarding),就是一個路由器。當啟動的時候,我們需要設置兩個埠:監聽埠(Listening Port)和目的主機(Destination Server)與目的埠(Desti... ...
  • 最近比較忙,好久沒寫博客了。個人感覺最好的進步就是寫東西。哈哈。 一般我們使用ADO.net從資料庫中讀取數據返回的集合是DataSet類型的。有時候我們需要進行轉換成List<T>集合。一般的做法是在DAL層中,寫個方法進行轉換。(每個表寫一個)。累哦!~ 所以我就想,能不能寫個工廠,傳入Data ...
  • 菜單和工具欄: 1. MenuStrip --頂部菜單分割線1. “-”號 ,2. 右鍵 插入 split 快捷鍵:每一個項右鍵屬性的最下麵可以設置快捷鍵不管選項隱藏還是菜單隱藏,快捷鍵都管用 2、ContextMenuStrip:右鍵菜單 每個控制項都可以有右鍵菜單 3、StatusStript:底 ...
  • Calendar 日曆; FileUpdate 文件上傳; Image 圖片,可以直接給URL; Repeater: HeaderTemplate - 在載入開始執行一遍 ItemTemplate - 有多少條數據,執行多少遍 FooterTemplate - 在載入最後執行一遍 Alternati ...
  • Repeater: HeaderTemplate - 在載入開始執行一遍 ItemTemplate - 有多少條數據,執行多少遍 FooterTemplate - 在載入最後執行一遍 AlternatingItemTemplate - 交替項模板 把性別0、1改成男女: 把民族顯示名稱替換代號: 調 ...
  • ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...