(转)制作web安装程序 dodo


出处:http://www/i-blog.cn/u/chenli/archives/2006/8.html

本文参考http://blog.csdn.net/libra1983/archive/2006/09/25/1274933.aspx

1、1.  打开VS2005,创建一个新的工程,选择:其他项目类型->安装和部署->安装项目。名称为Setup,确定。

2、2.    在文件系统中加入要安装的所有文件和文件夹。可在应用程序文件夹节点上单击鼠标右键,选择添加文件或文件夹。这里注意,如果要添加的文件夹中还有子文件夹这样添加会有点麻烦。可以先选择应用程序文件夹,在资源管理器中选择所有要安装的文件和文件夹,直接将选择的文件和文件夹拖放到VS2005的应用程序文件夹中(VS2005此时中间的部分)。

3、 3.   添加一个新项目,这里选择Visual C#的类库。用来在安装过程中添加MS Sql Server数据库,以及在IIS中创建网站。命名为SetupClassLibrary,确定。

4、4.    在安装数据库时,会执行脚本。在SetupClassLibrary项目中加入一个名为DBSQL.txt的文件,将要执行的脚本放在里面。将该文件的属性中生成操作属性设为:嵌入的资源。注意该脚本只是创建表和存储过程等,不是创建数据库的,而且不要含有“GO”命令,如果有“GO”命令可以用替换的方法把“GO”换成空白。

5、5.    删除SetupClassLibrary中自动生成的Class1.cs。在SetupClassLibrary中添加新的项。选择安装程序类。命名为SetupInstaller.cs,确定。

6、6.    SetupInstaller.cs的代码试图中可以看到SetupInstaller类继承自Installer。这里要重写Installer的几个方法,来处理安装过程中的行为。

7、7.    重写InstallerInstall方法。该方法在安装时执行。还可以重写Commit(完成)Rollback(回滚)Uninstall(卸载)SetupInstaller.cs中所有的代码在附录中。可以直接复制过来。需要添加的引用有:System.DirectoryServices。然后编译这个项目。

        public override void Install(IDictionary stateSaver)

        {

            base.Install(stateSaver);

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

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

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

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

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

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

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

            //写入获取的安装程序中的变量,此段代码为调试用可以不添加

            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))

            {

                throw new ApplicationException("创建数据库时出现严重错误!");

            }

            // 从备份数据库文件恢复数据库

            /*

            if (!RestoreDB(DBName))

            {

                throw new ApplicationException("恢复数据库时出现严重错误!");

            }

            */

 

            // 添加网站

            Connect();

            //string serverID = GetNextOpenID().ToString();

            //string serverComment = websitenName;

            // 下面的信息为测试,可以自己编写文本框来接收用户输入信息

            string serverID = "5555";

            string serverComment = "PortalSite";

            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("设置数据库连接字符串时出现错误");

            //}

            // 写注册表

            //WriteRegistryKey();

        }

8、8.    在安装项目Setup中打开用户界面编辑器,这里要在安装向导中加入设置数据库以及IIS的地方。在启动节点单击鼠标右键,添加对话框,把文本框(A)和文本框(B)都添加进来。把他们拖到确认安装的上面。

9、9.    设置文本框(A)的属性。BodyText:输入新网站的设置;Edit1Label:服务器;Edit1PropertyIISSERVEREdit1localhostEdit2Label:端口;Edit2PropertyPORTEdit29998Edit3VisibleFalseEdit4VisibleFalse

10.  设置文本框(B)的属性。BodyText:数据库设置;Edit1Label:数据库服务器;Edit1PropertyDBSERVERNAMEEdit1localhostEdit2Label:数据库名称;Edit2PropertyDBNAMEEdit2PortalEdit1Labe3:登录帐号;Edit3PropertyUSERNAME Edit4Label:密码;Edit4PropertyPASSWORD

11              加入自定义的操作。在安装项目Setup中打开自定义操作编辑器。在安装节点单击鼠标右键,添加自定义操作。双击应用程序文件夹,点击添加程序集按钮,选择“浏览”页,找到并选择SetupClassLibrary项目生成的程序集SetupClassLibrary.dll,确定。安装节点下多了一个SetupClassLibrary.dll节点,在该节点单击鼠标右键,选择属性,设置CustomActionData属性为/DBNAME=[DBNAME] /DBSERVERNAME=[DBSERVERNAME] /USERNAME=[USERNAME] /PASSWORD=[PASSWORD] /IISSERVER=[IISSERVER] /PORT=[PORT] /TARGETDIR="[TARGETDIR]\"

12.   先重新生成SetupClassLibrary项目,然后生成Setup项目。生成完毕后在Setup项目的Debug目录下可以找到Setup.msi文件和setup.exe文件。现在可以执行安装程序看看效果了。也可以在解决方案管理器的Setup项目节点上单击鼠标右键,选择安装。

 附录:SetupInstaller.cs的所有代码

using System.DirectoryServices;
using System.Management;
using System.Collections;
using System.Data;
using System;
using System.Reflection;
using System.IO;
using System.Configuration.Install;
using Microsoft.Win32;
using System.ComponentModel;


namespace SetupClassLibrary
{
    [RunInstaller(true)]
    public partial class SetupInstaller : Installer
    {
        public SetupInstaller()
        {
            InitializeComponent();
        }

        private System.Data.SqlClient.SqlConnection sqlConn=new System.Data.SqlClient.SqlConnection();

        private System.Data.SqlClient.SqlCommand Command;

        private string DBName;

        private string ServerName;

        private string AdminName;

        private string AdminPwd;

        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;

        #region ConnectDatabase 连接数据库

        private bool ConnectDatabase()
        {

            if (Command.Connection.State != ConnectionState.Open)
            {

                try
                {
                    Command.Connection.Open();

                }

                catch (Exception e)
                {
                    return false;

                }

            }

            return true;

        }

        #endregion


        #region GetSql 从文件中读取SQL,在读取包含SQL脚本的文件时需要用到,参考自MSDN


        private string GetSql(string Name)
        {

            try
            {

                Assembly Asm = Assembly.GetExecutingAssembly();

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

                StreamReader reader = new StreamReader(strm);

                return reader.ReadToEnd();

            }

            catch (Exception getException)
            {

                throw new ApplicationException(getException.Message);

            }

        }

        #endregion

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

        private void ExecuteSql(string DataBaseName, string sqlstring)
        {

            Command = new System.Data.SqlClient.SqlCommand(sqlstring, sqlConn);

            if (ConnectDatabase())
            {

                try
                {

                    Command.Connection.ChangeDatabase(DataBaseName);

                    Command.ExecuteNonQuery();

                }
                finally
                {

                    Command.Connection.Close();

                }

            }

        }

        #endregion

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

        protected bool CreateDBAndTable(string DBName)
        {

            bool Restult = false;

            //try
            //{
              
                ExecuteSql("master", "USE MASTER IF EXISTS (SELECT NAME FROM SYSDATABASES WHERE NAME='" + DBName + "') DROP DATABASE " + DBName);
               
                ExecuteSql("master", "CREATE DATABASE " + DBName);

                ExecuteSql(DBName, GetSql("DBSQL.txt"));
               
                Restult = true;

            //}
            //catch
            //{

            //}

            return Restult;

        }

        #endregion

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

        ///

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

        ///

        ///数据库名

        ///配件中数据库脚本资源的名称

        ///

        protected bool RestoreDB(string DBName)
        {

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

            bool Restult = false;

            string MSQL = "RESTORE DATABASE " + DBName +

                " FROM DISK = '" + dir + @"data.bak' " +

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

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

            try
            {

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

                ExecuteSql("master", MSQL);

                Restult = true;

            }

            finally
            {

                // 删除备份文件

                try
                {

                    File.Delete(dir + @"data.bak");

                }

                catch
                {

                }

            }

            return Restult;

        }

        #endregion

        #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("Missing config file :" + this.Context.Parameters["targetdir"] + "/web.config");

            }

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

            xmlLoad(FileInfo.FullName);

            bool FoundIt = false;

            foreach (System.Xml.XmlNode Node in xmlDocument["configuration"]["appSettings"])
            {

                if (Node.Name == "add")
                {

                    if (Node.Attributes.GetNamedItem("key"). == "ConnectionString")
                    {

                        Node.Attributes.GetNamedItem(""). = 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 (!FoundIt)
            {

                throw new InstallException("Error when writing the config web.config");

            }

            xmlSave(FileInfo.FullName);

            return FoundIt;

        }

        #endregion

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

        private void WriteRegistryKey()
        {

            // 写注册表

            RegistryKey hklm = Registry.LocalMachine;

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

            RegistryKey F = cqfeng.CreateSubKey("cqfeng");

            F.Set("FilePath", "kkkk");

        }

        #endregion

        #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"]. == 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["Return"].;

            }

            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"]. = HostName;

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

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

                serverBinding.Put();

                return serverBinding;

            }

            catch
            {

                return null;

            }

        }

        #endregion

        #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["DBSERVERNAME"].ToString();

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

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

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

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

            //写入获取的安装程序中的变量,此段代码为调试用可以不添加

            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))
            {
                throw new ApplicationException("创建数据库时出现严重错误!");
            }

            // 从备份数据库文件恢复数据库

            /*

            if (!RestoreDB(DBName))

            {

                throw new ApplicationException("恢复数据库时出现严重错误!");

            }

            */

            // 添加网站

            Connect();

            //string serverID = GetNextOpenID().ToString();

            //string serverComment = websitenName;

            // 下面的信息为测试,可以自己编写文本框来接收用户输入信息

            string serverID = "5555";

            string serverComment = "PortalSite";

            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("设置数据库连接字符串时出现错误");

            //}

            // 写注册表

            //WriteRegistryKey();
        }

        #endregion

        #region Uninstall 删除

        public override void Uninstall(IDictionary savedState)
        {

            if (savedState == null)
            {

                throw new ApplicationException("未能卸载!");

            }

            else
            {

                base.Uninstall(savedState);

            }

        }

        #endregion

原文地址:https://www.cnblogs.com/zgqys1980/p/558985.html