octverve的专栏

是的,我是为了生存才学它的,所以学的一般

用户操作
[即时聊天] [发私信] [加为好友]
octverveID:octverve
198150次访问,排名369好友0人,关注者126
octverve的文章
原创 108 篇
翻译 0 篇
转载 815 篇
评论 50 篇
最近评论
anan3000:装sp1就可以了吧,但我的没有vss哦
windz:这么简单的问题说半天.

假如MC是动态生成的,而非库中的元件又该如何解决呢?
octverve:从业多年,从无名到有名的企业,许多管理多采用这类方法……,应对方法很简“你不是我的上帝,所以你不能摆布我……”
octverve:从业多年,从无名到有名的企业,许多管理多采用这类方法……,应对方法很简“你不是我的上帝,所以你不能摆布我……”
only_endure:1:1
1:N
M:N
文章分类
收藏
    相册
    存档
    软件项目交易
    订阅我的博客
    XML聚合  FeedSky
    订阅到鲜果
    订阅到Google
    订阅到抓虾
    订阅到BlogLines
    订阅到Yahoo
    订阅到GouGou
    订阅到飞鸽
    订阅到Rojo
    订阅到newsgator
    订阅到netvibes

    转载 如何用VS2005制作Web安装程序 收藏

    新一篇: 用VS2005制作网页对IIS进行操作  | 旧一篇: Remoting基本原理及其扩展机制

    网站完成后,需要部署到目标机器上,方法有很多,直接把文件Copy到目标机器上,执行SQL脚本,配置IIS,这样可以做到;也可以使用InstallShield这样到专业制作软件来打包。本篇文章是使用VS2005自带到安装部署工具来制作exe安装文件。
     
    涉及到到内容包括:使用安装部署工具,建立数据库,配置IIS,文件操作,注册表等。参考了网上关于使用VS制作安装程序的文章。环境:Windows2003 + VS2005 + SQL2005。
    注:本文只是为了实现,没有强调方法,变量等的写法标准。
     
    使用VS2005制作安装程序的时候,有多种选择,如下图:
    我想一般常用的可能就最上面的两种。当使用Web安装项目时,执行制作好的msi安装文件时,会发现实际上是添加虚拟目录而不是添加网站,而且无法选择安装目录,当然,可以自己写脚本来对IIS进行修改。不过在这篇文章里,将不采用此模式。本篇文章用的是使用“安装项目”,就和打包WinForm程序一样,把Web文件部署到目标机器上,然后重写install方法,配置IIS,执行SQL脚本,修改web.config文件等。
     
    在开始整个过程之前,需要先了解一下“预编译”的概念,MSDN上的说明是:默认情况下,在用户首次请求资源(如网站的一个页)时,将动态编译 ASP.NET 网页和代码文件。第一次编译页和代码文件之后,会缓存编译后的资源,这样将大大提高随后对同一页提出的请求的效率。请查阅MSDN“预编译”相关文档。
     
    准备一个文件DBSQL.txt,在里面包含连接数据库后需要执行的SQL脚本,在本例中使用了简单的一个Create Tabel的SQL。
     
    好了,现在开干,吼吼~~~~~~~~~~
     
    打开VS2005,打开一个网站项目,这里是打开的本地localhost,如图:
    新加一个页面,随便取个名字(本文中为ClientCallback.aspx),然后写一个简单的按钮事件即可,这不是本文的重点,由你随意处理^_^ 再添加web配置文件即web.config,在下添加
                 
    此文件到时候是需要发布到目标机器上的。(关于连接数据库字符串,VS2005里面有专门的connectionStrings,本文未使用,可查阅帮助)
    点击生成网站,访问页面,ok!
    选择菜单生成=》发布网站:
    点击确定后,网站已经生成,这些就是需要部署到目标机器上的所有文件。
     
    点击菜单文件=》添加=》新建项目,添加安装部署项目,如图:
     
     
    添加安装项目类库:
    删除默认的Class1.cs,新加一个安装程序类文件,名为MyInstaller.cs
     
    在此项目中,添加对System.EnterpriseServices和System.DirectoryServices的引用,在操作IIS的时候,需要用到。在文件中添加:
    using System;
    using System.IO;
    using System.DirectoryServices;
    using System.Reflection;
    using System.Data;
    using System.Data.SqlClient;
    using System.Configuration.Install;
    using System.Management;
    using System.Collections;
    using Microsoft.Win32;
    using System.Collections.Specialized;如果编译的时候出错,请添加相关引用。
     
    修改文件如下图:
     
    注意要手动添加Installer!
     
    将DBSQL.txt文件放到此项目中,在属性中设置为“嵌入的资源”
     
    回到MyWebSetup项目,点击查看属性,可以设置安装文件到显示相关信息,如图
     
     
    选择文件系统,如图:
    然后:
     
    (在文件系统中,在属性里面可以设置安装程序默认到安装路径)
     
    添加一个叫bin文件夹并添加在生成网站时bin目录下的dll文件,如图:
     
    在应用程序文件夹下在生成网站时目录下的文件,添加后如图:
     
     
    选择“用户界面编辑器”,添加两个文本框A和B,A将作为安装新站点后的IIS设置,B将作为数据库操作时的参数设置,调整位置后如下:
    调整A的属性,这里只选择了显示两个输入框,属性分别为IISSERVER和PORT,值为localhost和9998,其他的你可以自己调整。如图:
     
    文本框B的设置如下:
    OK,文本框设置完毕。当然,你还可以选择其他的多种文本框,如协议什么的。
     
    打开自定义操作面板:
     
     
    然后:
    在CustomActionData中输入:
    /dbname=[DBNAME] /server=[DBSERVERNAME] /user=[USERNAME] /pwd=[PASSWORD] /iis=[IISSERVER] /port=[PORT] /targetdir="[TARGETDIR]\"
    这些参数就是文本框A和B上的输入框的值,在安装过程中可以获得,然后进行处理。
     
    至此,基本的安装文件已经制作完毕。进行生成,然后点击安装,可以看到文件已经复制到了相应到目录。接下来就要接收参数对IIS和数据库进行处理。
     
    打开SetupClassLibrary项目下的MyInstaller.Designer.cs,修改此文件。
    申明几个变量:
            private System.Data.SqlClient.SqlConnection sqlConn;
            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
    如果不能正确连接数据库服务器,请检查你的连接字符串,或者将连接字符串写入文件查看。不好意思,我不知道如何对这种安装部署程序进行debug,sorry咯!
     
    读取SQL文件的方法:
    #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
    可以将此需要执行的SQL脚本放在此文本中
     
    执行SQL语句的方法:
    #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
    这里可以到注册表读取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("Missing config file :" + this.Context.Parameters["targetdir"] + "/web.config");
                }
     
                System.Xml.XmlDocument xmlDocument = new System.Xml.XmlDocument();
                xmlDocument.Load(FileInfo.FullName);
     
                bool FoundIt = 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 (!FoundIt)
                {
                    throw new InstallException("Error when writing the config file: web.config");
                }
     
                xmlDocument.Save(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.SetValue("FilePath", "kkkk");
            }
            #endregion
     
    操作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["dir"];
     
                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();
               
                //写入获取的安装程序中的变量,此段代码为调试用可以不添加
                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 = "cqfeng";
                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
     
     
    编译,然后选择安装,如图:
    第一图:
    第二图:
     
    第三图:
    抱歉,我不知道在这里怎么使登录密码框输入时显示为*号
     
    第四图:
    第五图:
     
    安装:
    安装完成:
     
    安装后的IIS
     
    安装目录:
    安装后的数据库:
     
    至此,一个简单的部署web程序的exe文件已经完成,当然,省略了很多东西,比如,对安装机器的判断(IIS版本,Framework版本,SQL Server版本等),IIS站点属性等设置(默认页面,访问权限,执行权限等),卸载程序时应该删除的东西等等。这些东西,在MSDN里面可以查找到相关说明,如果你需要,只有辛苦一下了,嘿嘿。
    相信有了这些,自己用WinForm来写安装程序也时可以了哈。
     
    问题:安装的时候输入密码时无法显示为*号;安装文件夹中出现编译后的安装类编译后的dll文件。哪位大哥对这些比较熟悉的,指点指点……………..
     
    写得不是很仔细,如果有问题或者错误,请你自己多调试一下!
     

    发表于 @ 2007年09月22日 21:53:00|评论(loading...)|编辑

    新一篇: 用VS2005制作网页对IIS进行操作  | 旧一篇: Remoting基本原理及其扩展机制

    评论

    #zyhomepage 发表于2008-06-26 15:39:26  IP: 202.106.149.*
    运行通过,真不错!众佳网络
    发表评论  


    当前用户设置只有注册用户才能发表评论。如果你没有登录,请点击登录
    Csdn Blog version 3.1a
    Copyright © octverve