隐藏

C# Web项目制作安装包

发布:2020/7/7 17:14:15作者:管理员 来源:本站 浏览次数:1144

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 }
复制代码
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 [RunInstaller(true)]  17 public partial class unInstaller1 : System.Configuration.Install.Installer  18  {  19 public unInstaller1()  20  {  21  InitializeComponent();  22  }  23  24 private string _target;  25 private DirectoryEntry _iisServer;  26 private ManagementScope _scope;  27 private ConnectionOptions _connection;  28 /// <summary>  29 /// 卸载  30 /// </summary>  31 /// <param name="savedState"></param>  32 public override void Uninstall(IDictionary savedState)  33  {  34 base.Uninstall(savedState);  35 //System.Diagnostics.Debugger.Launch(); //调试代码  36 string serID = "66";  37 try  38  {  39  Connect();  40 string SiteID = IsWebSiteExists(serID);  41 if (SiteID == "") { return; }  42 else  43  {  44 //这里要获取保存的链接字符串  45 DirectoryEntry root = new DirectoryEntry("IIS://localhost/W3SVC");//参数只能这样写   46 DirectoryEntry site = (DirectoryEntry)root.Invoke("GetObject", "IIsWebServer", serID);//serID:为站点ID   47 DirectoryEntry siteVDir = site.Children.Find("Root", "IISWebVirtualDir");//参数只能这样写   48 string s = siteVDir.Properties["Path"].Value.ToString(); //安装地址  49 //判断文件是不是存在  50 string webconfigpath = "";  51 if (File.Exists(s + "App_Data\\log.txt"))  52  {  53 webconfigpath = Path.Combine(s + "App_Data\\", "log.txt");  54  55 string connectionString = File.ReadAllText(webconfigpath);  56 try  57  {  58 using (SqlConnection connection = new SqlConnection(connectionString))  59  {  60  connection.Open();  61 string sql = " if exists(select * from sysdatabases where name='jiaowuDB' )begin alter database jiaowuDB set single_user with rollback immediate   drop database jiaowuDB  end ";  62  ExecuteSQL(connection, sql);  63  connection.Close();  64  }  65 File.Delete(s + "App_Data\\log.txt");  66  }  67 catch (Exception es)  68  {  69 MessageBox.Show("删除数据失败,请手动删除!\n" + es.Message, "出错啦!");  70  }  71  }  72  DelSite(serID);  73  }  74  }  75 catch (Exception ex)  76  {  77 MessageBox.Show("卸载出错!\n" + ex.Message, "出错啦!");  78  }  79  80  }  81  82 #region Connect 连接IIS服务器  83 public bool Connect()  84  {  85 try  86  {  87 _iisServer = new DirectoryEntry("IIS://localhost/W3SVC/1");  88 _target = "localhost";  89 _connection = new ConnectionOptions();  90 _scope = new ManagementScope(@"//localhost/root/MicrosoftIISV2", _connection);  91  _scope.Connect();  92  }  93 catch  94  {  95  96 return false;  97  }  98 return IsConnected();  99  } 100 public bool IsConnected() 101  { 102 if (_target == null || _connection == null || _scope == null) return false; 103 return _scope.IsConnected; 104  } 105 #endregion 106 107 108 /// <summary> 109 /// 删除站点 110 /// </summary> 111 /// <param name="WebSiteName">站点ID</param> 112 public void DelSite(string WebSiteID) 113  { 114 try 115  { 116 string SiteID = IsWebSiteExists(WebSiteID); 117 if (SiteID == "") return; 118 119 DirectoryEntry deRoot = new DirectoryEntry("IIS://localhost/W3SVC"); 120 try 121  { 122 DirectoryEntry deVDir = new DirectoryEntry(); 123  deRoot.RefreshCache(); 124 deVDir = deRoot.Children.Find(SiteID, "IIsWebServer"); 125  deRoot.Children.Remove(deVDir); 126  deRoot.CommitChanges(); 127  deRoot.Close(); 128 return; 129  } 130 catch (System.Exception) 131  { 132 return; 133  } 134  } 135 catch (Exception e) 136  { 137 MessageBox.Show("error:删除站点失败." + e.Message); 138  } 139  } 140 141 #region IsWebSiteExists 判断网站是否已经存在 142 public string IsWebSiteExists(string serverID) 143  { 144 try 145  { 146 string siteName = "W3SVC/" + serverID; 147 ManagementObjectSearcher searcher = new ManagementObjectSearcher(_scope, new ObjectQuery("SELECT * FROM IIsWebServer"), null); 148 149 ManagementObjectCollection webSites = searcher.Get(); 150 foreach (ManagementObject webSite in webSites) 151  { 152 if ((string)webSite.Properties["Name"].Value == siteName) 153 return serverID; 154  } 155 156 return ""; 157  } 158 catch 159  { 160 return ""; 161  } 162  } 163 #endregion 164 165 166 /// <summary> 167 /// 执行sql语句 168 /// </summary> 169 /// <param name="connection"></param> 170 /// <param name="sql"></param> 171 void ExecuteSQL(SqlConnection connection, string sql) 172  { 173 SqlCommand cmd = new SqlCommand(sql, connection); 174  cmd.ExecuteNonQuery(); 175  } 176 177  } 178 }
复制代码

 

最后右键安装项目》生成

生成安装包

 安装流程预览:

 

 注:

我们有时间可以会有一些特殊要求,比如密文

这里我们就需要用到 数据库表编辑器(orca)了

orca下载地址:http://pan.baidu.com/s/1bpDoia7

使用orca打开刚生成的Setup.msi文件

选择control,找到你要编辑的文本框,将Attributes改成2097159 ,保存

这里我们是CustomTextA中Edit3

 

第一次发文,诸多不足,请多指教。