C# 之Asp.net 安装包的创建,打包数据库

[RunInstaller(true)]
    public partial class JSWyglInstaller : Installer
    {
        public JSWyglInstaller()
        {
           
            InitializeComponent();
        }
 
        #region 程序代码

    
        /// <summary>
        /// 数据库的操作
        /// </summary>
        #region  数据库的操作属性集合
        private System.Data.SqlClient.SqlConnection sqlConn;

        private System.Data.SqlClient.SqlCommand Command;

        private System.Data.SqlClient.SqlTransaction Trans;

        private string DBName;

        private string ServerName;

        private string AdminName;

        private string AdminPwd;
        ///dbname=[DBNAME] /server=[DBSERVERNAME] /user=[USERNAME] /pwd=PASSWORD] /iis=[IISSERVER] /port=[PORT] /targetdir="[TARGETDIR]\"
        #endregion
        /// <summary>
        ///IIS的操作
        /// </summary>
        #region IIS操作属性
        private string iis;

        private string port;

        private string dir;

        public static string VirDirSchemaName = "IIsWebVirtualDir";

        private string _target;

        private DirectoryEntry _iisServer;

        private ManagementScope _scope;

        private ConnectionOptions _connection;

        #endregion

       //连接数据库服务器到方法:
       #region ConnectDatabase 连接数据库

        private bool ConnectDatabase()
        {
            if (Command.Connection.State != ConnectionState.Open)
            {
                try
                {
                    Command.Connection.Open();
                }

                catch(Exception e)
                {
                   MessageBox.Show("打开数据库失败:"+e.Message);
                   return false;
                }

            }
            return true;
        }
        /// <summary>
        /// 开启事物
        /// </summary>
        private void BeginTrans()
        {
            if (Trans == null)
                Trans = sqlConn.BeginTransaction();
            if(Command.Transaction==null)
            Command.Transaction = Trans;
        }
        /// <summary>
        /// 提交事物
        /// </summary>
        private void CommitTrans()
        {
            if (Trans != null)
                Trans.Commit();
         
        }

        private void RollBack()
        {
            if (Trans != null)
                Trans.Rollback();
        }

        #endregion

       //如果不能正确连接数据库服务器,请检查你的连接字符串,或者将连接字符串写入文件查看
       //读取SQL文件的方法:
       #region GetSql 从文件中读取SQL,在读取包含SQL脚本的文件时需要用到,参考自MSDN

            private string GetSql(string Name)
            {

                try
                {
                    //MessageBox.Show("GetSql"+Name);
                    Assembly Asm = Assembly.GetExecutingAssembly();

              Stream strm = Asm.GetManifestResourceStream(Asm.GetName().Name + "."  Name);

                    StreamReader reader = new StreamReader(strm);

                    return reader.ReadToEnd();
                }
                catch (Exception getException)
                {
                    MessageBox.Show("读取文件错误:" + getException.Message);
                    return string.Empty;
                    //throw new ApplicationException("读取文件错误:"+getException.Message);
                }
            }

            #endregion

       //可以将此需要执行的SQL脚本放在此文本中
       //执行SQL语句的方法:

        #region ExecuteSql 执行SQL语句,参考自MSDN

        private void ExecuteSql(string DataBaseName, string sqlstring)
        {
            //MessageBox.Show("ExecuteSql:DataBaseName"+DataBaseName +"-SqlString:"+sqlstring);
            Command = new System.Data.SqlClient.SqlCommand(sqlstring, sqlConn);
            if (ConnectDatabase())
            {
                try
                {
                    Command.Connection.ChangeDatabase(DataBaseName);
                    Command.ExecuteNonQuery();
                    //MessageBox.Show("ChangeDataBaseSuccess");

                }
                finally
                {
                    Command.Connection.Close();
                }
            }
        }

        private void ExecuteSqlForTrans(string DataBaseName, string sqlstring)
        {
            //MessageBox.Show("ExecuteSql:DataBaseName"+DataBaseName +"-SqlString:"+sqlstring);
            if(Command==null)
            Command = new System.Data.SqlClient.SqlCommand(sqlstring, sqlConn);
            if (ConnectDatabase())
            {
                try
                {
                    BeginTrans();
                    Command.Connection.ChangeDatabase(DataBaseName);
                    Command.ExecuteNonQuery();
                    //MessageBox.Show("ChangeDataBaseSuccess");

                }
                catch(Exception ex)
                {
                    if (Trans != null)
                        Trans.Rollback();
                    Command.Connection.Close();
                    //throw new Exception("创建数据库 [" + DBName + "] 错误:" + ex.Message);
                    MessageBox.Show("创建数据库 [" + DBName + "] 错误:" + ex.Message);
                }
            }
        }


        #endregion

        //创建数据库及数据库表:
        #region CreateDBAndTable 创建数据库及数据库表,参考自MSDN

        protected bool CreateDBAndTable(string DBName)
        {
            bool Restult = false;

            try
            {
                //MessageBox.Show("CreateDBAndTable");
                if (string.IsNullOrEmpty(DBName))
                    return false;
                ExecuteSqlForTrans("master", "USE MASTER IF EXISTS (SELECT NAME FROM SYSDATABASES WHERE NAME='" + DBName + "') DROP DATABASE " + DBName);
                ExecuteSqlForTrans("master", "CREATE DATABASE " + DBName);
                ExecuteSqlForTrans(DBName, GetSql("DBSQL.txt"));
                CommitTrans();
                Restult = true;
            }

            catch (Exception ex)
            {
                MessageBox.Show("CreateDBAndTable"+ex.Message);
                //throw new Exception("创建数据库 [" + DBName + "] 错误:" + ex.Message);
            }
            finally
            {
                if(Command!=null)
                Command.Connection.Close();
            }

            return Restult;

        }

        #endregion


        //从备份文件恢复数据库及数据库表
        #region RestoreDB 从备份文件恢复数据库及数据库表

        ///
        /// 从备份文件恢复数据库及数据库表
        ///
        ///数据库名
        ///配件中数据库脚本资源的名称
        ///

        protected bool RestoreDB(string DBName)
        {
           string dir = this.Context.Parameters["targetdir"];

            //MessageBox.Show("DBDir:" + dir);

            dir += @"DBInit\";

            bool Restult = false;

            string MSQL = "RESTORE DATABASE " + DBName +

                " FROM DISK = N'" + dir + @"wygl.bak' " +

                " WITH MOVE 'TXFee_Data' TO  N'" + @"c:\" + DBName + ".mdf', " +

                " MOVE 'TXFee_log' TO N'" + @"c:\" + DBName + ".ldf' ";

            try
            {

                ExecuteSql("master", "USE MASTER IF EXISTS (SELECT NAME FROM SYSDATABASES WHERE NAME='" + DBName + "') DROP DATABASE " + DBName);
                ExecuteSql("master", MSQL);
                //CommitTrans();
                Restult = true;

            }
            catch(Exception ex)
            {
                MessageBox.Show("创建数据库 [" + DBName + "] 错误:" + ex.Message);
                //throw new Exception("创建数据库 [" + DBName + "] 错误:" + ex.Message);
            }
            finally
            {

                if (Command != null)
                    Command.Connection.Close();
                #region 作废
                // 删除备份文件
                //try
                //{

                //    File.Delete(dir + @"wygl.bak");

                //}
                //catch
                //{

                //}
                #endregion


            }
            return Restult;

        }

        #endregion

        //这里可以到注册表读取SQL Server的安装路径,把恢复后的数据库文件放到data目录地下。
        //在本例中,只是实现了恢复,并未进行标准的操作。其中Test和Test_log时备份时数据库的文件信息。
        //如果想要从备份文件中恢复,请把文件包含到项目里并且设置和DBSQL.txt一样,嵌入到程序里。最后执行删除。
        //不过我想应该有办法不把文件先安装到目标机器上,而是有方法想读取DBSQL.txt文件一样,直接恢复数据库,不过确实没想到办法,失败!
        //网站安装好后,需要设置web.config文件,这里只涉及到连接字符串到设置,其他的可以同理修改。

        #region WriteWebConfig 修改web.config的连接数据库的字符串

        private bool WriteWebConfig()
        {
      
            System.IO.FileInfo FileInfo = new System.IO.FileInfo(this.Context.Parameters["targetdir"] + "/web.config");

            if (!FileInfo.Exists)
            {

                throw new InstallException("未找到Web.Config文件 :" + this.Context.Parameters["targetdir"] + "/web.config");

            }
            System.Xml.XmlDocument xmlDocument = new System.Xml.XmlDocument();

            xmlDocument.Load(FileInfo.FullName);
        
            bool FoundIt = false,FondReportServer=false;

            foreach (System.Xml.XmlNode Node in xmlDocument["configuration"]["appSettings"])
            {
                if (Node.Name == "add")
                {
                    //根据安装设置连接字符串
                    //if (Node.Attributes.GetNamedItem("key").Value == "ConnectionString")
                    //{

                    //    Node.Attributes.GetNamedItem("value").Value = String.Format("Persist Security Info=False;Data Source={0};database={1};User ID={2};Password={3};Packet Size=4096;Pooling=true;Max Pool Size=100;Min Pool Size=1", ServerName, DBName, AdminName, AdminPwd);
                    //    FoundIt = true;                                           
                    //}
                    //根据安装设置连接字符串
                    if (Node.Attributes.GetNamedItem("key").Value == "SqlConnectionString")
                    {

                        Node.Attributes.GetNamedItem("value").Value = String.Format("Persist Security Info=False;Data Source={0};database={1};User ID={2};Password={3};Packet Size=4096;Pooling=true;Max Pool Size=100;Min Pool Size=1", ServerName, DBName, AdminName, AdminPwd);
                        FoundIt = true;
                    }
                    if (Node.Attributes.GetNamedItem("key").Value == "SqlConnectionADO")
                    {

                        Node.Attributes.GetNamedItem("value").Value = String.Format("Provider=SQLOLEDB.1;Password={3};Persist Security Info=False;User ID={2};Initial Catalog={1};Data Source={0}", ServerName, DBName, AdminName, AdminPwd);
                        FoundIt = true;
                    }
                    //根据安装设置连接字符串
                    if (Node.Attributes.GetNamedItem("key").Value == @"auV8CdDyCk/67slOZw5fh1KU7XuAjzSUq7ZCaBKfXsgHpdZ7RgCJHL0TWqbjkpIG")
                    {
                        string str= String.Format("Persist Security Info=False;Data Source={0};database={1};User ID={2};Password={3};Packet Size=4096;Pooling=true;Max Pool Size=100;Min Pool Size=1", ServerName, DBName, AdminName, AdminPwd);
                        Node.Attributes.GetNamedItem("value").Value = WYDAL.FangChan.StringUtils.CryptographyUtility(str);

                        FoundIt = true;
                    }
                    if (Node.Attributes.GetNamedItem("key").Value == "WebReportServer")
                    {
                        string [] dir=this.Context.Parameters["targetdir"].ToString().TrimEnd('\\').Split('\\');
                        //string dirRootString = this.Context.Parameters["targetdir"].ToString();
                        string dirRootName=string.Empty;
                        if(dir!=null && dir.Length>0)
                        {
                            dirRootName=dir[dir.Length-1];
                        }
                        //Node.Attributes.GetNamedItem("value").Value = String.Format("http://{0}/{1}/ReprotServer/YaWebReportService.asmx?WSDL",this.Context.Parameters["iis"] ,dirRootName );
                        Node.Attributes.GetNamedItem("value").Value = String.Format("http://{0}/WebReportServer/YaWebReportService.asmx?WSDL", this.Context.Parameters["iis"]);
                       // MessageBox.Show(this.Context.Parameters["targetdir"]);
                        FondReportServer = true;
                    }
                 
                }
            }
            if (!FoundIt )
            {
                throw new InstallException("查找配置文件的数据库服务信息出错!");
            }

            if( !FondReportServer)
            {
                 throw new InstallException("查找配置文件的报表服务器出错!");
            }
            xmlDocument.Save(FileInfo.FullName);

            return FoundIt;

        }
        /// <summary>
        /// 从WEBCONFIG 中获取数据库连接字符串
        /// </summary>
        /// <returns></returns>
        private string GetDBNameFromWebConfig()
        {

            //MessageBox.Show("webconfig");
            System.IO.FileInfo FileInfo = new System.IO.FileInfo(this.Context.Parameters["targetdir"] + "/web.config");

            if (!FileInfo.Exists)
            {
                throw new InstallException("Missing config file :" + this.Context.Parameters["targetdir"] + "/web.config");

            }
            System.Xml.XmlDocument xmlDocument = new System.Xml.XmlDocument();

            xmlDocument.Load(FileInfo.FullName);

           // bool FoundIt = false, FondReportServer = false;

            foreach (System.Xml.XmlNode Node in xmlDocument["configuration"]["appSettings"])
            {
                if (Node.Name == "add")
                {
                    if (Node.Attributes.GetNamedItem("key").Value == "SqlConnectionString")
                    {

                       string strNodeConnection= Node.Attributes.GetNamedItem("value").Value ;//= String.Format("Persist Security Info=False;Data Source={0};database={1};User ID={2};Password={3};Packet Size=4096;Pooling=true;Max Pool Size=100;Min Pool Size=1", ServerName, DBName, AdminName, AdminPwd);
                       if (string.IsNullOrEmpty(strNodeConnection))
                       {
                           int dataBaseIndex=strNodeConnection.IndexOf("database=")+10;
                           int dataBaseEnd = strNodeConnection.Substring(dataBaseIndex, strNodeConnection.Length - dataBaseIndex - 1).IndexOf(";");
                           MessageBox.Show(strNodeConnection.Substring(dataBaseIndex, dataBaseEnd));
                           return strNodeConnection.Substring(dataBaseIndex,dataBaseEnd);
                       }
                    }
                  
                }
            }
            return string.Empty;

        }


        #endregion


        #region WriteRegistryKey 写注册表。安装部署中,直接有一个注册表编辑器,可以在那里面设置。

        private void WriteRegistryKey()
        {
            // 写注册表

            RegistryKey hklm = Registry.LocalMachine;

            RegistryKey qzg = hklm.OpenSubKey("SOFTWARE", true);

            RegistryKey F = qzg.CreateSubKey("QzgWygl");

            //F.SetValue("FilePath", "kkkk"); old
            F.SetValue("FilePath", "QzgFxWygl");

        }

        #endregion

        //操作IIS,建立网站等。可参考:

        //用VS2005制作网页对IIS进行操作
        #region Connect 连接IIS服务器
        public bool Connect()
        {
            if (iis == null)

                return false;

            try

            {

                _iisServer = new DirectoryEntry("IIS://" + iis + "/W3SVC/1");

                _target = iis;

                _connection = new ConnectionOptions();

                _scope = new ManagementScope(@"\\" + iis + @"\root\MicrosoftIISV2", _connection);

                _scope.Connect();

            }

            catch

            {

               
                return false;

            }

            return IsConnected();

        }

        public bool IsConnected()

        {

            if (_target == null || _connection == null || _scope == null) return false;

            return _scope.IsConnected;

        }

        #endregion


        #region IsWebSiteExists 判断网站是否已经存在

        public bool IsWebSiteExists(string serverID)

        {

            try

            {

                string siteName = "W3SVC/" + serverID;

                ManagementObjectSearcher searcher = new ManagementObjectSearcher(_scope, new ObjectQuery("SELECT * FROM IIsWebServer"), null);

                ManagementObjectCollection webSites = searcher.Get();

                foreach (ManagementObject webSite in webSites)

                {

                    if ((string)webSite.Properties["Name"].Value == siteName)

                        return true;

                }

                return false;

            }

            catch

            {

                return false;

            }

        }

        #endregion


        #region GetNextOpenID 获得一个新的ServerID

        private int GetNextOpenID()

        {

            DirectoryEntry iisComputer = new DirectoryEntry("IIS://localhost/w3svc");

            int nextID = 0;

            foreach (DirectoryEntry iisWebServer in iisComputer.Children)
            {

                string sname = iisWebServer.Name;

                try

                {

                    int name = int.Parse(sname);

                    if (name > nextID)

                    {

                        nextID = name;

                    }

                }

                catch

                {

                }

            }

            return ++nextID;

        }

        #endregion


        #region CreateWebsite 添加网站

        public string CreateWebSite(string serverID, string serverComment, string defaultVrootPath, string HostName, string IP, string Port)

        {

            try

            {

                ManagementObject oW3SVC = new ManagementObject(_scope, new ManagementPath(@"IIsWebService='W3SVC'"), null);

                if (IsWebSiteExists(serverID))

                {

                    return "Site Already Exists...";

                }

                ManagementBaseObject inputParameters = oW3SVC.GetMethodParameters("CreateNewSite");

                ManagementBaseObject[] serverBinding = new ManagementBaseObject[1];

                serverBinding[0] = CreateServerBinding(HostName, IP, Port);

                inputParameters["ServerComment"] = serverComment;

                inputParameters["ServerBindings"] = serverBinding;

                inputParameters["PathOfRootVirtualDir"] = defaultVrootPath;

                inputParameters["ServerId"] = serverID;

               

                ManagementBaseObject outParameter = null;

                outParameter = oW3SVC.InvokeMethod("CreateNewSite", inputParameters, null);

               

                // 启动网站

                string serverName = "W3SVC/" + serverID;

                ManagementObject webSite = new ManagementObject(_scope, new ManagementPath(@"IIsWebServer='" + serverName + "'"), null);

                webSite.InvokeMethod("Start", null);

                return (string)outParameter.Properties["ReturnValue"].Value;

            }
            catch (Exception ex)
            {

                return ex.Message;

            }

        }


        //创建网站管理服务
        public ManagementObject CreateServerBinding(string HostName, string IP, string Port)

        {

            try

            {

                ManagementClass classBinding = new ManagementClass(_scope, new ManagementPath("ServerBinding"), null);

                ManagementObject serverBinding = classBinding.CreateInstance();

                serverBinding.Properties["Hostname"].Value = HostName;

                serverBinding.Properties["IP"].Value = IP;

                serverBinding.Properties["Port"].Value = Port;

                serverBinding.Put();

                return serverBinding;

            }

            catch

            {

                return null;

            }

        }

        #endregion

        //好了,准备工作已经做完,现在开始写最重要的Install方法了

        //整个方法写完后如下:

        #region Install 安装

        ///

        /// 安装数据库

        ///

        ///

        public override void Install(IDictionary stateSaver)

        {
            base.Install(stateSaver);

            dir = this.Context.Parameters["targetdir"];

            DBName = this.Context.Parameters["dbname"].ToString();
          
          
            ServerName = this.Context.Parameters["server"].ToString();
         

            AdminName = this.Context.Parameters["user"].ToString();
     

            AdminPwd = this.Context.Parameters["pwd"].ToString();
        

            iis = this.Context.Parameters["iis"].ToString();
        

            port = this.Context.Parameters["port"].ToString();
         
            //MessageBox.Show("Initial-"+DBName+"-"+ServerName+"-"+AdminName+"-"+AdminPwd+"-iis:"+iis+"-"+port+"-"+dir+"}");

            //写入获取的安装程序中的变量,此段代码为调试用可以不添加
            if(sqlConn==null)
            sqlConn = new SqlConnection();
            this.sqlConn.ConnectionString = "Packet size=4096;User ID=" + AdminName + ";Data Source=" + ServerName + ";Password=" + AdminPwd + ";Persist Security Info=False;Integrated Security=false";


            //本安装程序采用附加数据库的方式,所以去掉本段代码
            // 执行SQL 安装数据库 可选择时恢复或者时直接创建
            //if (!CreateDBAndTable(DBName))
            //{
            //    MessageBox.Show("qzg-dbname");
            //    throw new ApplicationException("创建数据库时出现严重错误!");

            //}


            // 从备份数据库文件恢复数据库
            if (!RestoreDB(DBName))
            {
                MessageBox.Show("恢复数据库时出现严重错误,请与管理员联系!");
            }
          
             //部署桌面快捷方式*******************#region//部署桌面快捷方式*******************
            string strDeskTop = System.Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
            StreamWriter sw2 = System.IO.File.CreateText(strDeskTop + "\\亿联物业管理系统.url");
            stateSaver.Add("DeskQuick", strDeskTop + "\\亿联物业管理系统.url"); //保存桌面快诫方式文件绝对地址
         
            string[] aryTh = dir.TrimEnd('\\').Split('\\');
            string webdirs = aryTh[aryTh.Length-1];

             string Urls = @"URL=http://"+iis+"/" + webdirs + @"/default.aspx";
             sw2.WriteLine("[InternetShortcut]");
             sw2.WriteLine(Urls);
             sw2.WriteLine("modified=228928983");
             sw2.WriteLine("IconIndex=0");
             sw2.WriteLine("IconFile=" + dir + "http://www.cnblogs.com/bingyun84/admin/file://wygl.ico/");
             sw2.Flush();
             sw2.Close();
             //#endregio
             ////部署开始菜单 ***************#region 部署开始菜单 ***************
             string startMenue=Environment.GetFolderPath(Environment.SpecialFolder.StartMenu);
            
             if(File.Exists(startMenue+"\\亿联物业管理系统.url"))
             {
                  if(MessageBox.Show("开始菜单已经存在,是否有覆盖它?","安装开始菜单",MessageBoxButtons.YesNo,MessageBoxIcon.Question,
                   MessageBoxDefaultButton.Button1) == DialogResult.Yes)
                  {

                      File.Copy(strDeskTop + "\\亿联物业管理系统.url", startMenue + "\\亿联物业管理系统.url", true);
                  }
                  else
                  {
                    throw new InstallException("开始菜单已经存在,安装取消");
                  }
             }
             else
             {
               
                 File.Copy(strDeskTop + "\\亿联物业管理系统.url", startMenue + "\\亿联物业管理系统.url", false);
             }
             stateSaver.Add("StartMenueFile",startMenue+"\\亿联物业管理系统.url"); //保存开始菜单文件绝对地址
 
            // 添加网站
            Connect();
            // 下面的信息为测试,可以自己编写文本框来接收用户输入信息

            string serverID = "5555";

            string serverComment = "QZG";

            string defaultVrootPath = this.Context.Parameters["targetdir"];

            if (defaultVrootPath.EndsWith(@"\"))
            {
                defaultVrootPath = defaultVrootPath.Substring(0, defaultVrootPath.Length-1);

            }

            string HostName = "";

            string IP = "";

            string Port = port;

            string sReturn = CreateWebSite(serverID, serverComment, defaultVrootPath, HostName, IP, Port);

            // 修改web.config
            if (!WriteWebConfig())
            {

                //throw new ApplicationException("设置数据库连接字符串时出现错误");
                MessageBox.Show("设置数据库连接字符串时出现错误");
             

            }
            // 写注册表
            WriteRegistryKey();
        }

        #endregion

        //删除时的方法。在本文中未详细操作,比如删除站点,删除数据库等。如果需要,请你自己补足

        #region Uninstall 删除

        //QZG
        private bool DeleteDatabase()
        {
            try
            {
                DBName = this.Context.Parameters["dbname"].ToString();
                if (string.IsNullOrEmpty(DBName))
                {
                  DBName=  GetDBNameFromWebConfig();
                }
                if (string.IsNullOrEmpty(DBName))
                    return false;
                ExecuteSql("master", "USE MASTER IF EXISTS (SELECT NAME FROM SYSDATABASES WHERE NAME='" + DBName + "') DROP DATABASE  "+DBName+" ");
                return true;

            }
            catch
            {
                return false;
            }
        }
        public override void Uninstall(IDictionary savedState)
        {
            //MessageBox.Show("卸载过程....");
            if (savedState == null)
                throw new ApplicationException("卸载数据库失败,未能卸载![qzg]");
            else
            {
                 base.Uninstall(savedState);
                 //删除快捷键,删除开始菜单#region 删除快捷键,删除开始菜单
                 //删除快捷键
                 if(File.Exists(savedState["DeskQuick"].ToString()))
                 {
                  File.Delete(savedState["DeskQuick"].ToString());
                 }
                 //删除开始菜单
                 if(File.Exists(savedState["StartMenueFile"].ToString()))
                 {
                  File.Delete(savedState["StartMenueFile"].ToString());
                 }
                 //#endregion
                if (!DeleteDatabase())
                {
                    MessageBox.Show("卸载数据库错误,请手动删除物业管理系统的数据库!");
                    //throw new ApplicationException("卸载过程中发生错误,未能卸载!");
                }
                   
            }

        }
        //END

        #endregion

        //end
        #endregion
    }

原文地址:https://www.cnblogs.com/bingyun84/p/1681566.html