你的位置:首页 > ASP.net教程

[ASP.net教程]C# Web项目制作安装包


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       try120       {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       catch128       {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     #endregion141 142     #region CreateWebsite 添加网站143     public string CreateWebSite(string serverID, string serverComment, string defaultVrootPath, string HostName, string IP, string Port)144     {145       try146       {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       try181       {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       catch191       {192         return null;193       }194     }195     #endregion196 197     #region IsWebSiteExists 判断网站是否已经存在198     public bool IsWebSiteExists(string serverID)199     {200       try201       {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       catch215       {216         return false;217       }218     }219     #endregion220 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   [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     #endregion106 107 108     /// <summary>109     /// 删除站点110     /// </summary>111     /// <param name="WebSiteName">站点ID</param>112     public void DelSite(string WebSiteID)113     {114       try115       {116         string SiteID = IsWebSiteExists(WebSiteID);117         if (SiteID == "") return;118 119         DirectoryEntry deRoot = new DirectoryEntry("IIS://localhost/W3SVC");120         try121         {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       try145       {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       catch159       {160         return "";161       }162     }163     #endregion164 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 }

unLibrary1

 

最后右键安装项目》生成

生成安装包

 安装流程预览:

 

 注:

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

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

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

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

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

这里我们是CustomTextA中Edit3

 

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