日期:2014-06-10  浏览次数:20475 次

   之前由于工作需要自己做一个一键部署的小工具,实现三个模块的功能:TFS操作创建映射并获取最新源代码;SQL Server数据库注册表配置数据库连接;IIS站点部署,生成可访问的IIS站点。由于是基于自己的工作环境下的开发,所以在TFS和SQL Server配置工具化实现,有一些点是默认按照公司的环境配置参数默认的,虽然不是广泛适用每一种情况的环境部署,但是在学习这三个模块的开发过程中,还是有很多东西是可以值得分享的。

   今天先分享一下,如何通过工具化实现IIS站点部署和配置,为了可复用性,IIS操作这次是将其封装成一个类,以方便调用。

   可以看一下工具的截图:由于这个只是为了节省开发部署环境的时间而开发的小工具,所以没那么高大上,还请各位看官包涵。

   

   进入正题:先从使用角度来讲解IIS操作,然后再深入到具体的IIS服务底层原理。

   【1】前提掌握要点:  

       (1)、IIS到目前经历了四个版本分别为 IIS4.0  IIS5.0 IIS6.0 IIS7.0,其中IIS6.0 IIS7.0是在5.0的安全问题的基础上获得的发展,目前为止。6.0版本以后的都是比较安全稳定的,为什么需要了解IIS版本,是因为6.0以后和之前的IIS提供的操作API是不一样的,不过IIS6.0时代主要以using System.DirectoryServices空间下的DirectoryEntry 对象作为编程访问一个主要载体.但随着IIS7.0发布.NET的Web程序由IIS6.0开始逐渐过渡到 7.0版本.而且在编程控制IIS上新添加的Microsoft.Web.Administration名称空间, 可以操作7.0

       (2)、平时的站点部署需要配置什么参数或者说是我们一般自己部署站点需要什么场景的操作,考虑可以用程序实现的,然后可以模型化为对象去实现。

        我采用的方案是:将部署的站点声明为一个对象,其中包含了一般我们站点部署时设置的参数作为它的属性和字段,将我们一般站点设置实现为一些方法。

        可以先定义一个站点类:

           

    //站点身份验证模式
    public enum autherRight {asp_net模拟, Form身份验证, Windows身份验证, 基本身份验证,匿名身份验证,摘要式身份验证 };
    /// <summary>
    /// 站点类
    /// </summary>
    public class newWebSiteInfo 
    { 
        //站点设置参数
        public string hostIp;  //主机ip
        public string porNum;  //端口号
        public string hostName;//主机名
        public string webName; //网站名
        public string appName; //应用程序池
        public string webPath; //根目录
        public string visualPath;//虚拟目录
        public Dictionary<string, string> newMimeType;//需要新添加mime类型
        public autherRight autherRight;//身份验证模式
        public string defoultPage;//默认文档

        public newWebSiteInfo(string hostip, string portnum, string hostname, string webname, string appName, string webpath, string visualPath, Dictionary<string, string> newMimeType, autherRight autherRight,string defoultPage) 
        {
            this.hostIp = hostip;
            this.porNum = portnum;
            this.hostName = hostname;
            this.webName=webname;
            this.appName = appName;
            this.webPath = webpath;
            this.visualPath = visualPath;
            this.newMimeType = newMimeType;
            this.autherRight = autherRight;
            this.defoultPage = defoultPage;
        }
        /// <summary>
        /// 返回站点绑定信息
        /// </summary>
        /// <returns></returns>
        public string bindString() 
        {
                return String.IsNullOrEmpty(hostName) ? String.Format("http://{0}:{1}", hostIp, porNum) : String.Format("http://{0}:{1}", hostName, porNum);
        }
    }

  目前IIS操作主要有两种方式:一种是System.DirectoryServices空间下面的类,用于IIS5/6版本,和可以兼容iis6的IIS7版本;Microsoft.Web.Administration空间下面的类,IIS7引入的新的管理类,主要通过ServerManger类进行站点新增。

  本次主要通过System.DirectoryServices方式操作IIS,也简要介绍一下ServerManger新建站点:

      (1) 添加.net引用 Microsoft.Web.Administration.dll,实例化ServerManger新增站点方式如下:

using System;
using Microsoft.Web.Administration;

class CreateASite
{
    static void Main(string[] args)
    {
        ServerManager serverManager = new ServerManager();
        Site mySite = serverManager.Sites.Add(
            "MySite", "d:\\inetpub\\mysite", 8080);
        mySite.ServerAutoStart = true;
        serverManager.CommitChanges();
    }
}

  (2)通过System.DirectoryServices空间下面的类获取IIS服务,但其实对于高版本的也可以同时引用Microsoft.Web.Administration.dll中通过ServerManger来进行参数设置各有各的好处。

  首先介绍一下我用到的几个命名空间:

  

using System.DirectoryServices;  //获取目录实体类
using Microsoft.Web.Administration; //ServerManger类所属命名空间using IISOle;                      //IIS管理添加mime类型
using System.Security.AccessControl; //设置文件安全权限类所属命名空间
using System.IO;                    //文件路径类所属命名空间
using System.ServiceProcess;        //上一节中所用的系统服务对象所属命名空间

  现在提供我自己的源代码,可以适用一般类需求,对于一些特殊配置的应用程序部署,可以稍微做微调。

  

///created by george
///date:2014-5-3
///QQ:709617880
namespace IISmng
{  
    //站点身份验证模式
    public enum autherRight {asp_net模拟, Form身份验证, Windows身份验证, 基本身份验证,匿名身份验证,摘要式身份验证 };
    /// <summary>
    /// 站点类
    /// </summary>
    public class newWebSiteInfo 
    { 
        //站点设置参数
        public string hostIp;  //主机ip
        public string porNum;  //端口号
        public string hostName;//主机名
        public string webName; //网站名
        public string appName; //应用程序池
        public string webPath; //物理路径
        public string visualPath;//虚拟目录
        public Dictionary<string, string> newMimeType;//需要新添加mime类型
        public autherRight autherRight;//身份验证模式
        public string defoultPage;//默认文档

        public newWebSiteInfo(string hostip, string portnum, string hostname, string webname, string appName, string webpath, string visualPath, Dictionary<string, string> newMimeType, autherRight autherRight,string defoultPage) 
        {
            this.hostIp = hostip;
            this.porNum = portnum;
            this.hostName = hostname;
            this.webName=webname;
            this.appName = appName;
            this.webPath = webpath;
            this.visualPath = visualPath;
            this.newMimeType = newMimeType;
            this.autherRight = autherRight;
            this.defoultPage = defoultPage;
        }
        /// <summary>
        /// 返回站点绑定信息
        /// </summary>
        /// <returns></returns>
        public string bindString() 
        {
                return String.IsNullOrEmpty(hostName) ? String.Format("http://{0}:{1}", hostIp, porNum) : String.Format("http://{0}:{1}", hostName, porNum);
        }
    }
    //托管模式
    public enum modelType{集成,经典};
    //net版本
    public enum netVersion{ v2_0 , v4_0};
    /// <summary>
    /// IIS操作类
    /// </summary>
    public class myIIS
    {  
        /// <summary>
        /// IIS版本属性
        /// </summary>
        public String IISVersion {

            get { return IISVersion; }

            set{
              DirectoryEntry IISService = new DirectoryEntry("IIS://localhost/W3SVC/INFO");
              IISVersion = "v"+IISService.Properties["MajorIISVersionNumber"].Value.ToString();
            }
        
        }

        /// <summary>
        /// 检测客户端或服务器是否安装IIS服务
        /// </summary>
        /// <returns>true OR false</returns>
        public Boolean checkIIS() {
            Boolean retMsg = false;
            try { 
                 DirectoryEntry IISService = new DirectoryEntry("IIS://localhost/W3SVC");
                 if(IISService.GetType().ToString().Equals("DirectoryEntry"))
                 {
                     if (checkServiceIsRunning("IIS Admin Service"))
                            retMsg=true;
                 }
            }
            catch(Exception e){

            }
            return retMsg;
        }

        /// <summary>
        /// 检测服务是否开启
        /// </summary>
        /// <param name="serviceName"></param>
        /// <returns></returns>
        public Boolean checkServiceIsRunning(string serviceName)
        {
            ServiceController[] allServices = System.ServiceProcess.ServiceController.GetServices();
            Boolean runing = false;
            foreach (ServiceController sc in allServices)
            {
                if (sc.DisplayName.Trim() == serviceName.Trim())
                {
                    if (sc.Status.ToString() == "Running")
                    {
                        runing = true;
                    }
                }
            }
            return runing;
        }
        /// <summary>
        /// 获取本机IIS版本
        /// </summary>
        /// <returns></returns>
        public String getIISVersion() {
            String retStr = "";
            if (checkIIS())
            {
                DirectoryEntry IISService = new DirectoryEntry("IIS://localhost/W3SVC/INFO");
                 retStr = "v"+IISService.Properties["MajorIISVersionNumber"].Value.ToString();
            }
            return retStr;
        }

        /// <summary>
        /// 判断程序池是否存在
        /// </summary>
        /// <param name="AppPoolName">程序池名称</param>
        /// <returns>true存在 false不存在</returns>
        private bool isAppPoolExist(string AppPoolName)
        {
            bool result = false;
            DirectoryEntry appPools = new DirectoryEntry("IIS://localhost/W3SVC/AppPools");
            foreach (DirectoryEntry appPool in appPools.Children)
            {
                if (appPool.Name.Equals(AppPoolName))
                {
                    result = true;
                }
            }
            return result;
        }

        /// <summary>
        /// 创建应用程序池
        /// </summary>
        /// <param name="appName">自定义引用程序池名</param>
        /// <param name="type">托管类型</param>
        /// <param name="netV">.net版本</param>
        /// <returns></returns>
        public DirectoryEntry creatAppPool(string appName, modelType type, netVersion netV)
        {

            if (!isAppPoolExist(appName))
            {
                DirectoryEntry newpool;
                DirectoryEntry appPools = new DirectoryEntry("IIS://localhost/W3SVC/AppPools");
                newpool = appPools.Children.Add(appName, "IIsApplicationPool");
                //修改应用程序池配置
                setModalAndNetVersionOfappPool(appName, type, netV);
                newpool.CommitChanges();
                return newpool;
            }
            else return null;

        }

        /// <summary>
        /// 删除指定程序池
        /// </summary>
        /// <param name="AppPoolName">程序池名称</param>
        /// <returns>true删除成功 false删除失败</returns>
        private bool deleteAppPool(string AppPoolName)
        {
            bool result = false;
            if (isAppPoolExist(AppPoolName)) return result;
            DirectoryEntry appPools = new DirectoryEntry("IIS://localhost/W3SVC/AppPools");
            foreach (DirectoryEntry appPool in appPools.Children)
            {
                if (appPool.Name.Equals(AppPoolName))
                {
                    try
                    {
                        appPool.DeleteTree();
                        result = true;
                    }
                    catch
                    {
                        result = false;
                    }
                }
            }
            return result;
        }

        /// <summary>
        /// 设置应用程序池的托管模式和.net版本
        /// </summary>
        /// <param name="appPoolName"></param>
        /// <param name="modelType"></param>
        /// <param name="netVersion"></param>
        public void setModalAndNetVersionOfappPool(string appPoolName, modelType mt, netVersion nv) {
            if (String.IsNullOrEmpty(appPoolName)) return;
            if (isAppPoolExist(appPoolName)) return;
            if (nv == null) return;
            if (mt == null) return;
            ServerManager sm = new ServerManager();
            if (nv == netVersion.v2_0)
            {
                sm.ApplicationPools[appPoolName].ManagedRuntimeVersion = "v2.0";
            }
            else if (nv == netVersion.v4_0) {

                sm.ApplicationPools[appPoolName].ManagedRuntimeVersion = "v4.0";
            }

            if (mt == modelType.集成) 
            {
                sm.ApplicationPools[appPoolName].ManagedPipelineMode = ManagedPipelineMode.Integrated;
            }
            else if(mt==modelType.经典)
            {
                sm.ApplicationPools[appPoolName].ManagedPipelineMode = ManagedPipelineMode.Classic; //托管模式Integrated为集成 Classic为经典
            }
            sm.CommitChanges();

        }

        /// <summary>
        ///检测网站名是否可用
        /// </summary>
        /// <param name="siteInfo"></param>
        /// <returns>true 可用,false 不可用过</returns>
        public bool checkWebNameIsAvailble(string webComment)
        {
            //检测网站名是否可用
            bool isAvalable = true;
            DirectoryEntry serviceEntry = new DirectoryEntry("IIS://localhost/W3SVC");
            foreach (DirectoryEntry entry in serviceEntry.Children)
            {
                if (entry.SchemaClassName == "IIsWebServer")
                {
                    string webName = entry.Properties["ServerComment"].Value.ToString();

                    if (webName == webComment)
                    {
                        isAvalable = false;
                        break;
                    }
                }
            }
            return isAvalable;
        }

        /// <summary>
        /// 检测端口号是否已被占用
        /// 注意:端口号输入有限制,在调用该方法前,需要做端口号合理性校验
        /// </summary>
        /// <param name="portNum"></param>
        /// <returns></returns>
        public bool checkPortIsVailble(string portNum) {
            bool isVailble = true;
            DirectoryEntry serviceEntry = new DirectoryEntry("IIS://localhost/W3SVC");
            foreach (DirectoryEntry entry in serviceEntry.Children)
            {
                if (entry.SchemaClassName == "IIsWebServer")
                {
                    if (entry.Properties["ServerBindings"].Value != null)
                    {
                        string Binding = entry.Properties["ServerBindings"].Value.ToString().Trim();
                        string[] Info = Binding.Split(':');
                        if (Info[1].Trim() == portNum)
                        {
                            isVailble = false;
                            break;
                        }
                    }
                }

            }
            return isVailble;
        }
       
        /// <summary>
        /// 创建网站
        /// </summary>
        /// <param name="siteInfo"></param>
        public DirectoryEntry creatNewWeb(newWebSiteInfo siteInfo,modelType type,netVersion netV)
        {
           
            DirectoryEntry Services = new DirectoryEntry("IIS://localhost/W3SVC");
            int webID = 0;
            foreach (DirectoryEntry server in Services.Children)
            {
                if (server.SchemaClassName == "IIsWebServer")
                {
                    if (Convert.ToInt32(server.Name) > webID)
                    {
                        webID = Convert.ToInt32(server.Name);
                    }
                }
            }
            webID++;

            //创建站点
            DirectoryEntry mySitServer = Services.Children.Add(webID.ToString(), "IIsWebServer");
            mySitServer.Properties["ServerComment"].Clear();
            mySitServer.Properties["ServerComment"].Add(siteInfo.webName);
            mySitServer.Properties["Serverbindings"].Clear();
            mySitServer.Properties["Serverbindings"].Add(":" + siteInfo.porNum + ":");
            mySitServer.Properties["Path"].Clear();//注意该path为站点的路径,新增站点时,两者目录一致
            mySitServer.Properties["path"].Add(siteInfo.webPath);
            mySitServer.Properties["DefaultDoc"].Add(siteInfo.defoultPage);//设置默认文档
           
            //创建虚拟目录
            DirectoryEntry root = mySitServer.Children.Add("Root", "IIsWebVirtualDir");
            root.Properties["path"].Clear();//该路劲属性是站点下虚拟路径的路径,类似于站点的子路径
            root.Properties["path"].Add(siteInfo.visualPath);

           
            if (string.IsNullOrEmpty(siteInfo.appName))
            {
                root.Invoke("appCreate", 0);
            }
            else
            {
                
                //创建引用程序池
                string appPoolName = siteInfo.appName;
                if (!isAppPoolExist(appPoolName))
                {
                    DirectoryEntry newpool;
                    DirectoryEntry appPools = new DirectoryEntry("IIS://localhost/W3SVC/AppPools");
                    newpool = appPools.Children.Add(appPoolName, "IIsApplicationPool");
                    newpool.CommitChanges();

                }
                //修改应用程序池配置
                setModalAndNetVersionOfappPool(appPoolName, type,netV);
                root.Invoke("appCreate3", 0, appPoolName, true);
            }
            
            root.Properties["AppFriendlyName"].Clear();
            root.Properties["AppIsolated"].Clear();
            root.Properties["AccessFlags"].Clear();
            root.Properties["FrontPageWeb"].Clear();
            root.Properties["AppFriendlyName"].Add(root.Name);
            root.Properties["AppIsolated"].Add(2);
            root.Properties["AccessFlags"].Add(513);
            root.Properties["FrontPageWeb"].Add(1);

            root.CommitChanges();
            mySitServer.CommitChanges();

            return mySitServer;

        }
        /// <summary>
        /// 设置站点新增自定义mime类型,一次添加一个类型
        /// </summary>
        /// <param name="siteInfo"></param>
        /// <param name="mysiteServer"></param>
        public void addMIMEtype(newWebSiteInfo siteInfo,DirectoryEntry mysiteServer)
        {
            //需要添加新的mime类型
            if (siteInfo.newMimeType.Count > 0)
            {
                IISOle.MimeMapClass NewMime = new IISOle.MimeMapClass();
                NewMime.Extension = siteInfo.newMimeType.Keys.ToString(); NewMime.MimeType = siteInfo.newMimeType.Values.ToString();
                IISOle.MimeMapClass TwoMime = new IISOle.MimeMapClass();
                mysiteServer.Properties["MimeMap"].Add(NewMime);
                mysiteServer.CommitChanges();
            }

        }

        /// <summary>
        /// 设置文件夹权限 处理给EVERONE赋予所有权限
        /// </summary>
        /// <param name="FileAdd">文件夹路径</param>
        public void SetFileRole(newWebSiteInfo siteInfo)
        {
            DirectoryInfo dir_info = new DirectoryInfo(siteInfo.webPath);
            DirectorySecurity dir_security = new DirectorySecurity();
            dir_security.AddAccessRule(new FileSystemAccessRule("Everyone ", FileSystemRights.WriteData, AccessControlType.Allow));
            dir_info.SetAccessControl(dir_security);
        }

        /// <summary>
        /// 删除网站
        /// </summary>
        /// <param name="webName"></param>
        public void deletWeb(string webName) {
            DirectoryEntry Services = new DirectoryEntry("IIS://localhost/W3SVC");
            foreach (DirectoryEntry server in Services.Children)
            {
                if (server.SchemaClassName == "IIsWebServer")
                {
                    if (server.Properties["ServerComment"].Value == webName || server.Name==webName) 
                    {
                        server.DeleteTree();
                        break;
                    }
                }
            }

            Services.CommitChanges();
        }
    }
}

这个类方法中估计还有一些问题,还需要花时间细化,这次先将自己的初步实现做了总结,后面还会继续对这一块的内容作细化和深入学习……

  发现要把一个东西总结出来还是比较花精力的,今天暂时休息一下,后面深入的内容待续,持续更新……

 

当初在网上找关于IIS操作方面的资料,找了很多都是水贴,花了很多时间去找到收藏了一些比较好的分享,也是自己后来多亏看了这些朋友的总结,才慢慢对这一块有所熟悉。

现在在这里分享一下我自己参考的几篇资料:

 http://www.soft-bin.com/html/2010/07/28/use_csharp_to_control_iis.html  其中这一篇写的最好最详细,他也是将自己的方法封装起来,可以下载调用。

 http://www.jb51.net/article/35147.htm

http://www.make-awesome.com/2010/12/automating-iis7-setup-with-microsoft-web-administration/   这是一篇老外的博客,里面主要是用ServerManger来创建站点的一些说明,是比较简单一些。