• 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             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("删除数据失败,请手动删除! " + 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("删除数据失败,请手动删除!
    " + es.Message, "出错啦!");
     70                         }
     71                     }
     72                     DelSite(serID);
     73                 }
     74             }
     75             catch (Exception ex)
     76             {
     77                 MessageBox.Show("卸载出错!
    " + 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 }
    unLibrary1

    最后右键安装项目》生成

    生成安装包

     安装流程预览:

     注:

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

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

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

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

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

    这里我们是CustomTextA中Edit3

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

  • 相关阅读:
    freemarker写select组件报错总结(七)
    freemarker写select组件(四)
    AIX 安装和卸载MQ软件
    freemarker写select组件(三)
    freemarker写select组件报错总结(六)
    freemarker写select组件报错总结(五)
    Linux s位设置
    libevent多线程使用事项
    对libevent+多线程服务器模型的C++封装类
    vs2010下libevent的使用
  • 原文地址:https://www.cnblogs.com/fish520/p/5882450.html
Copyright © 2020-2023  润新知