C#操作IIS完整解析

本文涉及的产品
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
全局流量管理 GTM,标准版 1个月
简介: 原文:C#操作IIS完整解析最近在为公司实施做了一个工具,Silverlight部署早已是轻车熟路, 但对于非技术人员来说却很是头疼的一件事,当到现场实施碰到客户情况也各不相同, 急需一个类似系统备份的"一键工具"快速实现应用程序部署和数据库进行关联.
原文: C#操作IIS完整解析

最近在为公司实施做了一个工具,Silverlight部署早已是轻车熟路, 但对于非技术人员来说却很是头疼的一件事,当到现场实施碰到客户情况也各不相同, 急需一个类似系统备份的"一键工具"快速实现应用程序部署和数据库进行关联. 网上关于这方面资源也比较混乱,其中对于IIS的编程影响因素很多,操作技巧上加以细化小结.

A:版本问题

这是你在进行编程前必须要要考虑的一个实际问题.因为IIS版本不同对应编程上基本上完全不同方式来进行的.先了解一下Iss版本在操作系统个具体要求.

2010-07-26_090116

 

 

 

 

 

 

ISS6.0时代主要以using System.DirectoryServices空间下的DirectoryEntry 对象作为编程访问一个主要载体.但随着ISS7.0发布.NET的Web程序由ISS6.0开始逐渐过渡到 7.0版本.而且在编程控制ISS上新添加的Microsoft.Web.Administration名称空间, 提出多个用于管理 操作 和访问ISS的对象, 使操作ISS的编程更加简洁 高效.

B:我们要做什么

实际用户操作环境中主要以Windows XP/2000/2003操作系统为主, 这就导致了ISS版本主要在5.0/5.1/6.0之间,所以本次演示的代码编程实例都是ISS7.0版本以下(不包含Iss7.0).

为了达到演示目的,我们现在需求是这样的: 把硬盘上Silverlight应用程序成功部署到本地机器ISS上. 并支持通过局域网访问. 需求很简单吧就是一句话, 其实当进入实际编程时因为客户的局域网环境是不可预知的, 这也就导致影响部署Silverlight程序到ISS上诸多未知因素. 所以要在编程中使Silverlight应用程序部署成功,我们必须利用编程除了控制ISS外还要控制其他主要影响ISS因素.

C:进入编程

既然提出需求我们大概确定一下解决思路:

2010-07-26_094356

 

 

 

 

 

 

 

在默认站点下创建一个虚拟目录承载Silverlight 应用程序, 新建的虚拟目录运行在独立应用程序池中, 支持本地局域网匿名访问其实就是对访问权限控制, 为了直接使更改的应用生效需要多次重新启动ISS的服务, 这就需要对ISS服务进行编程控制.

<1>ISS版本的获取

在进入客户环境前我们先检测下是否存在安装了ISS,以及ISS版本获取提示,目前获取ISS版本的方式主要有两种,第一种方法是通过遍历DirectoryEntry实体目录 第二种方式是通过获取注册表的ISS修改版本值[经测试这种方式获取版本不稳定].

   1:   public static void GetIssVersionByDri(string domainname)
   2:      {       
   3:           try
   4:            {
   5:                if (string.IsNullOrEmpty(domainname))
   6:                {
   7:                  //如果为空 则默认为本地机器
   8:                    domainname = "LOCALHOST";
   9:                }
  10:                DirectoryEntry getEntity=new DirectoryEntry("IIS://" + domainname + "/W3SVC/INFO");
  11:                string Version=getEntity.Properties["MajorIISVersionNumber"].Value.ToString();
  12:                MessageBox.Show(Version);
  13:            }
  14:            catch (Exception se)
  15:            {
  16:                //说明一点:IIS5.0中没有(int)entry.Properties["MajorIISVersionNumber"].Value;属性,将抛出异常 证明版本为 5.0
  17:                MessageBox.Show("获取ISS的版本是发生异常信息:"+se.Message);
  18:            }
  19:      }

通过系统注册表获取ISS版本的值:[测试发现不稳定]

   1:  public static string GetIssVersion()
   2:  {
   3:    //RegistryKey表示 Windows 注册表中的项级节点.此类是注册表封装
   4:    string issversion = string.Empty;
   5:    RegistryKey getkey = Registry.LocalMachine.OpenSubKey("software\\microsoft\\inetstp");
   6:    if (getkey != null)
   7:     {
   8:       issversion= Convert.ToInt32(getkey.GetValue("majorversion", -1)).ToString();
   9:       MessageBox.Show(issversion.ToString());
  10:     }
  11:    return issversion;
  12:  }
 <2>创建虚拟目录

每个Internet服务可以从多个目录中发布,通过以通用命名约定 (UNC) 名、用户名及用于访问权限的密码指定目录,可将每个目录定位在本地驱动器或网络上,虚拟目录可以一个宿主程序,这可发布的操作目录即为虚拟目录.再来看看在ISS6.0中创建的虚拟目录的步骤和控制的属性.

 2010-07-26_103114

 

 

 

 

 

 

 

 

新建虚拟目录:

   1:        /// <summary>
   2:        /// 添加一个虚拟目录
   3:        /// </summary>
   4:        public void CreateVirtualDir(string virtualdirname, string logicDir)
   5:        {
   6:            //如果存在重复 就直接删除虚拟目录 
   7:            if (IsExitesVirtualDir(virtualdirname))
   8:                DeleteVirtualDir(virtualdirname);
   9:   
  10:            DirectoryEntry rootEntry;
  11:            rootEntry = new DirectoryEntry("IIS://localhost/W3SVC/1/root");
  12:   
  13:            DirectoryEntry newVirDir;
  14:            newVirDir = rootEntry.Children.Add(virtualdirname, "IIsWebVirtualDir");
  15:            newVirDir.Invoke("AppCreate", true);
  16:   
  17:            newVirDir.CommitChanges();
  18:            rootEntry.CommitChanges();
  19:   
  20:            newVirDir.Properties["AnonymousPasswordSync"][0] = true;
  21:            newVirDir.Properties["Path"][0] = logicDir;//+ @"virtualdirentry\virtualname\";
  22:   
  23:            //设置的端口绑定数据
  24:            //_newVirDir.Properties["ServerBindings"].Value =AppEntitys.WebAppInfor.HostIp+AppEntitys.WebAppInfor.HostProt+AppEntitys.WebAppInfor.AppDesc;
  25:     
  26:            //设置起始默认页:
  27:            newVirDir.Properties["EnableDefaultDoc"][0] = true;
  28:            newVirDir.Properties["DefaultDoc"][0] = "Default.aspx";
  29:   
  30:            //_newVirDir
  31:            newVirDir.CommitChanges();
  32:        }
这个方法在创建时主要有两个参数 一个是新建虚拟目录名称 另外一个要部署Silverlight应用程序物理路径.在获取根节目录时需要制定ISS的路径. ISS的路径格式如:IIS://ComputerName/Service/Website/Directory

2010-07-26_154839

 

 

 

 

 

 

 

 

 

 

找到根目录后添加新建虚拟目录. 制定参数为Schema-指每个结点的类型:IIsVirtualDir:——虚拟目录 IIsWebDir :——普通目录, 添加完成后调用ADSI中的"AppCreate"方法将目录真正创建.创建完成后通过根目录和新目录提交保存.

<3>目录属性设置

在DirectoryEntity虚拟目录属性可以说是非常多的,当时在编程时我为了区分属性间区别做了一个方法去遍历整个属性集合PropertyCollection. 然后把常用重要的属性跳出来进入赋值设置. 因为关于虚拟目录的属性在MSDN上的API中并没有直接提到, 特别是对虚拟目录访问权限控制非常重要属性等 .先说明局部的常用的属性:

2010-07-26_160903

 

 

 

 

 

 

 

 

 

例如修改程序起始页:

   1:    //设置起始默认页:
   2:      newVirDir.Properties["EnableDefaultDoc"][0] = true;
   3:      newVirDir.Properties["DefaultDoc"][0] = "Default.aspx,Index.Html,index.asp";
   4:      newVirDir.CommitChanges();

DefaultDoc选项可以支持多个但注意选择性排序.一般修改目录属性后都选通过CommitChanges()方法提交保存, 但有时你会发现我明明修改属性 却没有保存生效. 这是因为ISS中部分属性设置需要重新启动ISS服务才能生效.这个时候我们需要对ISS服务进行控制.

<4>ISS服务控制

关于ISS服务控制微软提供一个命名空间System.ServiceProcess 提供能够快速操作本地系统服务API.对于ISS服务控制我们最常用的是重新启动使当前设置生效. 在设置服务时我先找到服务名称,打开计算机管理 在服务和应用程序目录下打开服务.

2010-07-26_162031

 

 

 

 

我们能看到ISS服务命名是:ISSAdmin 我们通过编码来控制:启动ISS.

   1:  //获取IIS Serivcer控制声明 . 参数为Server在系统标识该服务的简称,.
   2:  ServiceController getservicecon = new ServiceController("IISADMIN");
   3:  getservicecon.Start();

重启/暂停/停止ISS服务:

   1:   if (getservicecon.Status == ServiceControllerStatus.Running)
   2:       {
   3:            //停止服务
   4:            getservicecon.Stop();
   5:            //暂停服务
   6:            getservicecon.Pause();
   7:            //重启服务
   8:            //Process提供对本地和远程进程的访问并使您能够启动和停止本地系统进程
   9:            //利用Start方法调用:启动(或重用)此 Process 组件的 StartInfo 属性指定的进程资源,并将其与该组件关联
  10:            //如果启动了进程资源,则为 true;如果没有启动新的进程资源(例如,如果重用了现有进程),则为 false
  11:            //通过指定文档或应用程序文件的名称来启动进程资源,并将资源与新的 Process 组件关联 
  12:            Process.Start("iisreset");
  13:       }

如上就是简单利用编程有效控制ISS服务运行状态.

<5>应用程序池创建与控制

ISS应用程序池是将一个或多个应用程序链接到一个或多个工作进程集合的配置。因为应用程序池中的应用程序与其他应用程序被工作进程边界分隔,所以某个应用程序池中的应用程序不会受到其他应用程序池中应用程序所产生的问题的影响, 当我们新建一个应用程序时 有时客户端环境我们无法清除预知, 为了尽量减少影响ISS设置外在因素, 我们把新建虚拟目录放到一个独立应用程序池中.

当创建一个虚拟目录后,也同时创建一个程序池 把虚拟目录放到其中:

   1:        /// <summary>
   2:        /// 建立程序池后关联相应应用程序及虚拟目录
   3:        /// </summary>
   4:        public static void SetAppToPool(string appname)
   5:        {
   6:            //获取目录
   7:            DirectoryEntry getdir = new DirectoryEntry("IIS://localhost/W3SVC");
   8:            foreach (DirectoryEntry getentity in getdir.Children)
   9:            {
  10:                if (getentity.SchemaClassName.Equals("IIsWebServer"))
  11:                {
  12:                     //设置应用程序程序池 先获得应用程序 在设定应用程序程序池
  13:                     //第一次测试根目录
  14:                    foreach (DirectoryEntry getchild in getentity.Children)
  15:                    {
  16:                        if (getchild.SchemaClassName.Equals("IIsWebVirtualDir"))
  17:                        {
  18:                            //找到指定的虚拟目录.
  19:                            foreach (DirectoryEntry getsite in getchild.Children)
  20:                            {
  21:                                if (getsite.Name.Equals(appname))
  22:                                {
  23:                                    //【测试成功通过】
  24:                                    getsite.Properties["AppPoolId"].Value = appname;
  25:                                    getsite.CommitChanges();
  26:                                }
  27:                            }
  28:                        }
  29:                    }
  30:                }
  31:            }
  32:        }

思路如下: 首先获得ISS的根目录即ISS://localhost/W3SVC. 获取成功后通过SchemaClassName获取节点类型.ISSWebServer普通目录 ISSWebVirturalDir虚拟目录. 通过虚拟目录的Name唯一名称获取指定虚拟目录, 在通过属性参数AppPoolId设置附属的应用程序池的名称. 然后提交保存.

其实通过应用我们可以清晰看到ISS中各个目录之间的关联关系.上面是修改一个已经存储在应用程序池,如何创建:

   1:        public static bool CreateAppPool(string metabasePath, string appPoolName, string Username, string Password)
   2:        {
   3:            bool issucess = false;
   4:            try
   5:            {
   6:                if (metabasePath.EndsWith("/W3SVC/AppPools"))
   7:                {
   8:                    if (MyIISHelper.AppPoolExist(appPoolName))
   9:                    {
  10:                        //已经存在 先删除这个AppPool 在创建
  11:                        //MessageBox.Show("当前以站点名称命名的程序池已经存在!");  
  12:                        DeleteRepPool(appPoolName);
  13:                    }
  14:                  
  15:                        //创建一个新程序池
  16:                        DirectoryEntry newpool;
  17:                        DirectoryEntry apppools = new DirectoryEntry(metabasePath);
  18:                        newpool = apppools.Children.Add(appPoolName, "IIsApplicationPool");
  19:   
  20:                        //设置属性 访问用户名和密码 一般采取默认方式
  21:                        newpool.Properties["WAMUserName"][0] = Username;
  22:                        newpool.Properties["WAMUserPass"][0] = Password;
  23:                        newpool.Properties["AppPoolIdentityType"][0] = "3";
  24:                        newpool.CommitChanges();
  25:                }
  26:                return issucess;
  27:            }
  28:            catch// (Exception ex) 
  29:            {
  30:                return false;
  31:            }
  32:        }

基本上和创建一个DirectoryEntity雷同但注意指定的Schome类型是IIsApplicationPool用来标识创建的是一个应用程序池.当然创建可以删除 删除方式如下:

   1:  DirectoryEntry appPool = new DirectoryEntry("IIS://localhost/W3SVC/AppPools");
   2:   foreach (DirectoryEntry getdir in appPool.Children)
   3:     {
   4:         if (getdir.Name.Equals(appname))
   5:            {
   6:              getdir.DeleteTree();//删除
   7:            }
   8:     }

关于应用程序池如果不做任何设置则在ISS中会被DefaultPool中添加, 但有时默认程序池设置环境不一定能够满足当前程序需求,例如最常见的关于.NET版本的控制. 其中对3.0和3.5版本应用设置需要重新注册3.5 .NET FrameWork.部分组件这就涉及到一个.NET版本问题.

<6>.NET版本问题

在进行ISS控制中当然也是遇到各种各样的问题, 一方面因为测试XP 2003系统环境不同, 需要控制因素过多,当然其中值得一提就是关于整个应用程序池的.NET版本问题.我们先来看看多版本下ISS中设置:

2010-07-26_165844

 

 

 

 

 

 

 

 

 

如果我们的应用程序使用3.0或3.5版本 则在应用程序池的没有对应的.NET版本.这时应用程序运行会提示一个Http错误404.17 notFound:

image_thumb

 

 

 

 

 

 

 

 

 

 

 

其实ISS在处理应用程序池于.NET版本进行映射时,Net3.0\3.5没带处理程序aspnet_isapi.dll,所以IIS中指定网站适用框架时,这也是为什么我们在ISS映射时看不到.Net3.0\3.5版本. 最直接的方法重新注册.NET 3.5 由.NET 2.0版本托管: 这时我们需要执行一个Cmd命令:2010-07-26_174038

 

 

 

 

 

 

 

 

 

 

 

从新把应用程序池.net版本切换成.net 2.0.同样实现.net 3.0/3.5托管.

<7>使用环境以及测试条件

如上应用程序和代码均在Windows 7./XP2/Windows Server 2003上通过. 对应的ISS版本范围从ISS5.0/5.1到Iss 6.0/7.0. 包含ISS7.0. 篇幅有限,实际中关于ISS的操作还有很多细节问题不能面面俱到,我只是挑了其中我认为基础或几位重要几个问题着重来写, 实际中关于ISS还有其他诸多因素, 所以对于这方面控制编程 只能折中的有目的性选择自己想做的效果. 切不可贪大求全. 因为这本身控制过程就是复杂的过程. 客户环境也不能诸如统一. 如有疑问请在留言中回复我.

目录
相关文章
|
3月前
|
C# Windows
visual studio 2022 社区版 c# 环境搭建及安装使用【图文解析-小白版】
这篇文章提供了Visual Studio 2022社区版C#环境的搭建和安装使用指南,包括下载、安装步骤和创建C#窗体应用程序的详细图文解析。
visual studio 2022 社区版 c# 环境搭建及安装使用【图文解析-小白版】
|
3月前
|
开发框架 安全 .NET
文件上传绕过】——解析漏洞_IIS6.0解析漏洞
文件上传绕过】——解析漏洞_IIS6.0解析漏洞
66 4
|
21天前
|
编译器 C# 开发者
C# 9.0 新特性解析
C# 9.0 是微软在2020年11月随.NET 5.0发布的重大更新,带来了一系列新特性和改进,如记录类型、初始化器增强、顶级语句、模式匹配增强、目标类型的新表达式、属性模式和空值处理操作符等,旨在提升开发效率和代码可读性。本文将详细介绍这些新特性,并提供代码示例和常见问题解答。
34 7
C# 9.0 新特性解析
|
20天前
|
C# 开发者
C# 10.0 新特性解析
C# 10.0 在性能、可读性和开发效率方面进行了多项增强。本文介绍了文件范围的命名空间、记录结构体、只读结构体、局部函数的递归优化、改进的模式匹配和 lambda 表达式等新特性,并通过代码示例帮助理解这些特性。
30 2
|
3月前
|
开发框架 安全 应用服务中间件
【文件上传绕过】——解析漏洞_IIS7.0 | IIS7.5 | Nginx的解析漏洞
【文件上传绕过】——解析漏洞_IIS7.0 | IIS7.5 | Nginx的解析漏洞
154 9
|
4月前
|
前端开发 开发者 C#
深度解析 Uno Platform 中的 MVVM 模式:从理论到实践的全方位指南,助你轻松掌握通过 C# 与 XAML 构建高效可维护的跨平台应用秘籍
【8月更文挑战第31天】本文详细介绍如何在优秀的跨平台 UI 框架 Uno Platform 中实施 MVVM(Model-View-ViewModel)模式,通过一个简单的待办事项列表应用演示其实现过程。MVVM 模式有助于分离视图层与业务逻辑层,提升代码组织性、易测性和可维护性。Uno Platform 的数据绑定机制使视图与模型间的同步变得高效简便。文章通过构造 `TodoListViewModel` 类及其相关视图,展示了如何解耦视图与模型,实现动态数据绑定及命令处理,从而提高代码质量和开发效率。通过这一模式,开发者能更轻松地构建复杂的跨平台应用。
58 0
|
4月前
|
前端开发 开发者 Apache
揭秘Apache Wicket项目结构:如何打造Web应用的钢铁长城,告别混乱代码!
【8月更文挑战第31天】Apache Wicket凭借其组件化设计深受Java Web开发者青睐。本文详细解析了Wicket项目结构,帮助你构建可维护的大型Web应用。通过示例展示了如何使用Maven管理依赖,并组织页面、组件及业务逻辑,确保代码清晰易懂。Wicket提供的页面继承、组件重用等功能进一步增强了项目的可维护性和扩展性。掌握这些技巧,能够显著提升开发效率,构建更稳定的Web应用。
106 0
|
4月前
|
前端开发 程序员 API
从后端到前端的无缝切换:一名C#程序员如何借助Blazor技术实现全栈开发的梦想——深入解析Blazor框架下的Web应用构建之旅,附带实战代码示例与项目配置技巧揭露
【8月更文挑战第31天】本文通过详细步骤和代码示例,介绍了如何利用 Blazor 构建全栈 Web 应用。从创建新的 Blazor WebAssembly 项目开始,逐步演示了前后端分离的服务架构设计,包括 REST API 的设置及 Blazor 组件的数据展示。通过整合前后端逻辑,C# 开发者能够在统一环境中实现高效且一致的全栈开发。Blazor 的引入不仅简化了 Web 应用开发流程,还为习惯于后端开发的程序员提供了进入前端世界的桥梁。
390 0
|
5月前
|
SQL 开发框架 前端开发
在C#开发中使用第三方组件LambdaParser、DynamicExpresso、Z.Expressions,实现动态解析/求值字符串表达式
在C#开发中使用第三方组件LambdaParser、DynamicExpresso、Z.Expressions,实现动态解析/求值字符串表达式
|
5月前
|
SQL 安全 数据库
Ruby on Rails 数据库迁移操作深度解析
【7月更文挑战第19天】Rails 的数据库迁移功能是一个强大的工具,它帮助开发者以版本控制的方式管理数据库结构的变更。通过遵循最佳实践,并合理利用 Rails 提供的迁移命令和方法,我们可以更加高效、安全地管理数据库结构,确保应用的稳定性和可扩展性。