执着
有了梦想才有了执着,而只有执着才能实现梦想

导航

 

web项目打包过程中数据库配置文件、以及虚拟目录、端口设置方式,具体如下:

第一步:创建一个空白的解决方案

           1、打开vs平台,点击【新建】--》【项目】,进入新建项目窗口;

           2、在项目类型中选择【其他类型项目】--》【安装和部署】,然后在右侧模版中选择【web安装项目】,录入项目名称WebSetupSln,点击确定;

 

第二步:创建安装过程中定义具体操作工程

          1、在解决方案WebSetupSln上点击鼠标右键,点击【添加】--》【新建项目】,弹出【添加新项目】对话框,如下所示:

           

           2、在其中选择【类库】,填写项目名称InstallLibruary,点击确定

           3、删除新添加项目中默认文件Class1.cs,在项目上右键,点击【添加】--》【新建项】,进入【添加新项】,在其中选择【安装程序类】,录入名称WebInstaller.cs,点击确定

 第三步:安装包项目输出添加

           1、将需要打包的程序发布到指定目录

           2、运行当前整个解决方案,然后选择前面添加web安装项目,点击右键---【添加】---【项目输出】,弹出【添加项目输出组】对话框,在其中选择InstallLibruary,然后选择下面列表框中的【主输出】,点击确定

           3、在项目上点击右键--【视图】--【文件系统】,打开安装项目文件系统,在左侧列表中选择对应的【web应用程序文件夹】,然后将(1)中发布的文件复制之后粘贴到右边窗口中

(其实在该处操作有两种情况,如果你需要发布的是网站,可以按照该操作执行,如果你需要打包的是web应用程序,需要像(2)中步骤,将在项目输出中添加尽可,不过需要选择主输出与内容文件两项,这里就不作说明了)

 

第四步:在安装项目中添加自定义操作

           1、右击安装项目--【视图】--【用户界面】,在左侧显示用户界面,右击【启动】--【添加对话框】,在其中选择【文本框A】、【文本框B】,点击确定(如果需要许可协议等其他的,同样在此处添加,具体不做详细说明)

           2、回到用户界面,将添加的文本框A、文本框B移动到安装地址上方

           3、编辑文本框A属性,具体内容如下如:

           

          

          

           上述两个属性框中,A主要用于设置项目对应数据库配置、B主要用于web站点配置,在这里设置时需要注意EDITAPROPERTY与EDITAValue项,其中EDITAPROPERTY主要是在后面【自定义操作】设置时与对应的字符串相呼应,EDITAValue则为安装过程中对应项的默认值。

 

           4、在安装项目上右击,点击【视图】--【自定义操作】,在左侧打开自定义操作界面,右击【安装】--【添加自定义操作】,弹出选择框,在对话框中双击【web应用程序文件夹】,选择其中InstallLibruary主输出项。然后会在【安装】下面出现【主输出来自InstallLibruary(活动)】项目,按F4,在右侧出现其属性项、设置CustomActionData属性:

/dbname=[DBNAME] /dbserver=[DBSERVER] /user=[USERNAME] /pwd=[PASSWORD] /port=[IISPORT]  /virtualdir=[VIRTUALDIR] /targetdir="[TARGETDIR]\"

上面红色内容为(3)中设置的EDITAPROPERTY项,其中TARGETDIR为安装地址,对于web项目来讲,是基于iis根目录下的相对目录,这个至于如何设定成自定义的俺没搞懂。蓝色的内容将在后面InstallLibruary项目中具体编码时使用到,后面会有提及。

 

 第四步:自定义操作具体代码实现

             1、完成上面步骤之后,就需要为上述定义的自定义功能添加具体实现,首先打开InstallLibruary项目中的WebInstaller.cs,其中代码实现如下,逐步做出说明:

 

[RunInstaller(true)]
    public partial class WebInstaller: Installer
    {
        private string dbname;

        private string dbserver;

        private string user;

        private string pwd;

        private string port;

        private string physicaldir;

        private string virtualdir;

 

        public WebInstaller()
        {
            InitializeComponent();
        }

        

        #region Install  从这里开始启动安装

        public override void Install(IDictionary stateSaver)
        {
            try
            {
                base.Install(stateSaver);
                physicaldir = this.Context.Parameters["targetdir"].ToString();  //获取物理路径,对于web站点来讲是相对iis根目录的相对路径,一般使用虚拟目录名称即可
                virtualdir = this.Context.Parameters["virtualdir"].ToString();  //获取虚拟目录
                dbname = this.Context.Parameters["dbname"].ToString(); //获取数据库名称
                dbserver = this.Context.Parameters["dbserver"].ToString(); //获取服务器名称
                user = this.Context.Parameters["user"].ToString(); //用户名
                pwd = this.Context.Parameters["pwd"].ToString(); //密码
                port = this.Context.Parameters["port"].ToString(); //iis服务器

                

                string defaultdoc =  "Default.aspx" ; //默认首页

                // 创建虚拟目录
                CreateSite(port, virtualdir, defaultdoc);
                // 修改web.config
                WriteWebConfig();

                //创建数据库,该部分执行起来我感觉比较麻烦,要求数据库服务器在本机,如果不在本机数据库还是安装不上,一般web项目数据库服务器都是分离的,所以直接手动附加或者还原更简单(个人看法,呵呵)
                //if (AddDBTable(dbname) == -1)
                //{
                //    MessageBox.Show("数据库安装失败,如果确认数据库不在当前机器上,请手工在数据库服务器上进行附加!");
                //}
            }
            catch (Exception ee)
            {
                throw new Exception(ee.Message);
            }

        }

        #endregion

 

 

          public void CreateSite(string port, string siteExplain, string defaultDoc)
        {
            DirectoryEntry de = new DirectoryEntry("IIS://localhost/" + "w3svc");   //从活动目录中获取IIS对象。 对于服务器来讲,就是【网站】那个节点  
            int siteID = 1;  //下属站点ID,通过下属方法找到没有使用的网站ID
            oreach (DirectoryEntry e in de.Children)
            {
                if (e.SchemaClassName == "IIsWebServer")   //IIsWebServer表示网站
         {
                    int ID = Convert.ToInt32(e.Name);
                    if (ID >= siteID)
                    {
                        siteID = ID + 1;
                    }
                }
            }
            // Create web site
            DirectoryEntry site = (DirectoryEntry)de.Invoke("Create", "IIsWebServer", siteID);  //创建网站
            te.Properties["KeyType"][0] = "IIsWebServer";
            site.Properties["ServerComment"][0] = siteExplain; //站点说明  
            site.Properties["ServerState"][0] = 2; //站点初始状态,1.停止,2.启动,3  
            site.Properties["ServerSize"][0] = 1;
            site.Properties["ServerBindings"].Add(":" + port + ":"); //站点端口  

            site.CommitChanges(); //保存改变  
            de.CommitChanges();

            DirectoryEntry root = site.Children.Add("Root", "IIsWebVirtualDir");   //添加站点下虚拟目录对象  

            root.Invoke("AppCreate", true); //创建IIS应用程序   

            root.Properties["path"][0] = physicaldir ; //虚拟目录指向的物理目录  
            root.Properties["EnableDirBrowsing"][0] = false;//目录浏览  
            root.Properties["AuthAnonymous"][0] = false;
            root.Properties["AccessExecute"][0] = false;   //可执行权限  
            root.Properties["AccessRead"][0] = true;
            root.Properties["AccessWrite"][0] = true;
            root.Properties["AccessScript"][0] = true;//纯脚本  
            root.Properties["AccessSource"][0] = false;
            root.Properties["FrontPageWeb"][0] = false;
            root.Properties["KeyType"][0] = "IIsWebVirtualDir";
            root.Properties["AppFriendlyName"][0] = siteExplain; //应用程序名    
            root.Properties["AppIsolated"][0] = 2;
            root.Properties["DefaultDoc"][0] = defaultDoc; //默认文档  
            root.Properties["EnableDefaultDoc"][0] = true; //是否启用默认文档  
            root.CommitChanges();
            site.CommitChanges();
            root.Close();
            site.Close();
            de.CommitChanges(); //保存  
            site.Invoke("Start", null); //除了在创建过程中置初始状态外,也可在此调用方法改变状态  
        }

 

        private void WriteWebConfig()
        {
            int c = 20;
            //加载配置文件
            try
            {
                c++;
                System.IO.FileInfo FileInfo = new System.IO.FileInfo(this.Context.Parameters["targetdir"] + "/web.config");
                if (!FileInfo.Exists)
                {
                    throw new InstallException("缺少配置文件 :" + this.Context.Parameters["targetdir"] + "/web.config");
                }
                c++;
                System.Xml.XmlDocument xmlDocument = new System.Xml.XmlDocument();
                xmlDocument.Load(FileInfo.FullName);
                c++;
                //修改连接字符串
                foreach (System.Xml.XmlNode Node in xmlDocument["configuration"]["appSettings"])
                {
                    if (Node.Name == "add")
                    {
                        c++;
                        if (Node.Attributes.GetNamedItem("key").Value == "ConnectionString")
                        {
                            c++;
                            Node.Attributes.GetNamedItem("value").Value = String.Format("Database={0};Server={1};Uid={2};Pwd={3};", dbname, dbserver, user, pwd);

                        }

                    }
                }

                xmlDocument.Save(FileInfo.FullName);
            }
            catch
            {
                throw new Exception("数据库配置修改出错!");
            }

        }

         
        private void ExecuteSql(string connStr, string DatabaseName, string Sql)
        {
            SqlConnection conn = new SqlConnection(connStr);
            SqlCommand cmd = new SqlCommand(Sql, conn);


            conn.Open();
            conn.ChangeDatabase(DatabaseName);
            try
            {
                cmd.ExecuteNonQuery();
            }
            finally
            {
                conn.Close();
            }
        }


        /// <summary>
        /// 创建数据库
        /// </summary>
        /// <param name="strDBName"></param>
        protected int AddDBTable(string strDBName)
        {
            try
            {
                string strconn = "Data Source=" + this.Context.Parameters["dbserver"] +
              ";Initial Catalog=master;Persist Security Info=True;User ID=" + this.Context.Parameters["user"] + ";Password=" + this.Context.Parameters["pwd"] + "";

                //ExecuteSql(strconn,"master", "CREATE   DATABASE   " + strDBName);

                string strSql = "EXEC sp_attach_db  @dbname  =  N'" + this.Context.Parameters["dbname"] + "',"
                                 + "@filename1  =  N'" + this.Context.Parameters["targetdir"] + "DataBase\\Space.mdf',"
                                 + "@filename2  =  N'" + this.Context.Parameters["targetdir"] + "DataBase\\Space_log.ldf'";
                ExecuteSql(strconn, "master", strSql);

                return 0;
            }
            catch
            {
                return -1;
            }
        }

        
        #region Uninstall 删除

        public override void Uninstall(IDictionary savedState)
        {
            //添加自定义的卸载代码
            if (savedState == null)
            {
                throw new ApplicationException("未能卸载!");
            }

            else
            {
                base.Uninstall(savedState);
            }

        }

        #endregion

       }

 

至此基本结束了,如果添加网站不是使用端口,直接使用域名的话,可以使用下面代码,这个我具体还没有测试过,大家可以试试

 

public int CreateWebSite(string webSiteName, string pathToRoot, string bd) //创建网站
        {
            DirectoryEntry root = new DirectoryEntry("IIS://localhost/W3SVC");
            // Find unused ID value for new web site
            int siteID = 1;
            foreach (DirectoryEntry e in root.Children)
            {
                if (e.SchemaClassName == "IIsWebServer")
                {
                    int ID = Convert.ToInt32(e.Name);
                    if (ID >= siteID)
                    {
                        siteID = ID + 1;
                    }
                }
            }
            // Create web site
            DirectoryEntry site = (DirectoryEntry)root.Invoke("Create", "IIsWebServer", siteID);
            site.Invoke("Put", "ServerComment", webSiteName);//网站名称
            site.Invoke("Put", "ServerBindings", bd);//二级域名绑定
            site.Invoke("Put", "ServerState", 2);//默认4
            site.Invoke("Put", "DefaultDoc", "index.htm,index.asp,index.aspx,Default.aspx");
            site.Invoke("Put", "ServerAutoStart", 1);//开启站点
            site.Invoke("SetInfo");
            DirectoryEntry siteVDir = site.Children.Add("ROOT", "IISWebVirtualDir");
            siteVDir.Invoke("AppCreate", true); //创建应用程序站点
            siteVDir.CommitChanges();
            site.CommitChanges();
            siteVDir.Properties["AppIsolated"][0] = 2;//默认2
            siteVDir.Properties["Path"][0] = pathToRoot;//主目录路径
            siteVDir.Properties["AccessFlags"][0] = 513;
            siteVDir.Properties["FrontPageWeb"][0] = 1;
            siteVDir.Properties["AppRoot"][0] = "/LM/W3SVC/" + siteID + "/Root";
            siteVDir.Properties["AppFriendlyName"][0] = "默认应用程序";
            siteVDir.Properties["AspEnableParentPaths"][0] = true; //父路径启用
            siteVDir.CommitChanges();
            site.CommitChanges();
            return siteID;
        }

 

 

这东西感觉没啥,实际上因为一直发布web项目都直接拷贝发布就行了,比较方便,所以从来没有这样搞过,这次整的有点烦躁,花了好几天,看了很多别人代码,拿过来没法用,老是报错,后来发现就是在创建网站跟目录时报1001错误,后来通过遍历站点的方式最终ok了,写下来,看看对大家有没有用。

 

posted on 2011-08-19 18:15  jueq  阅读(949)  评论(0编辑  收藏  举报