65.9K
CodeProject 正在变化。 阅读更多。
Home

通过 C# 操作 IIS 应用程序池

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.33/5 (3投票s)

2015年12月11日

CPOL

2分钟阅读

viewsIcon

37749

一篇文章,描述了如何通过 C# 控制 IIS 应用程序池的操作。

引言

在某些情况下,我们需要通过 C# 远程重启 IIS 应用程序池。本技巧旨在实现这一点,适用于任何已安装 IIS 的目标服务器。

背景

有很多方法可以检查状态、停止和启动远程服务器上的应用程序池。虽然 System.DirectoryService.DirectoryEntry 方法提供了执行此操作的简单三行代码,但我们仍然需要一个更简洁的代码,以便在受限的环境下执行操作。

WMI 为我们提供了大量方法来完成这项任务。此代码同时使用 C# 和 WMI 方法,提供一个健壮的应用程序,可以在 99.99% 的环境中工作(在非常安全的的环境中,可能存在 0.1% 的例外情况)。

IIS 和应用程序池概念

Internet Information Services (IIS) 是微软为 Windows 系列创建的可扩展的 Web 服务器。IIS 支持 HTTP、HTTPS、FTP、FTPS、SMTP 和 NNTP。

我们可以将不同的 Web 应用程序和网站分成称为应用程序池的组。应用程序池是由一个或多个 URL 组成的组,由工作进程或一组工作进程提供服务。任何 Web 目录或虚拟目录都可以分配到应用程序池。

当您希望确保应用程序和网站的机密性和安全性时,请使用多个应用程序池。例如,一家企业组织可以将人力资源网站和财务网站放在同一服务器上,但位于不同的应用程序池中。

IIS WMI 提供程序

与其他选项(如服务、计算机详细信息、进程等)一样,IIS 也可以通过 WMI 进行控制。类由 IIS WMI 提供程序在 MicrosoftIISv2 命名空间中实现。从 Windows XP 和 Windows Server 2003 SP1 开始,任何使用 WMI 远程访问 IIS 的脚本都必须加密连接,否则将出现 WBEM_ACCESS_DENIED 错误。必须在调用期间设置此身份验证属性。

代码 # 1

下面的代码包含两个函数:一个用于确定应用程序池的状态

private bool IsApplicationPoolRunning(string servername, string strAppPool)
        {
            string sb = ""; // String to store return value

            // Connection options for WMI object
            ConnectionOptions options = new ConnectionOptions();

            // Packet Privacy means authentication with encrypted connection.
            options.Authentication = AuthenticationLevel.PacketPrivacy;

            // EnablePrivileges : Value indicating whether user privileges 
            // need to be enabled for the connection operation. 
            // This property should only be used when the operation performed 
            // requires a certain user privilege to be enabled.
            options.EnablePrivileges = true;

            // Connect to IIS WMI namespace \\root\\MicrosoftIISv2
            ManagementScope scope = new ManagementScope(@"\\" + 
            	servername + "\\root\\MicrosoftIISv2", options);

            // Query IIS WMI property IISApplicationPoolSetting
            ObjectQuery oQueryIISApplicationPoolSetting = 
            	new ObjectQuery("SELECT * FROM IISApplicationPoolSetting");

            // Search and collect details thru WMI methods
            ManagementObjectSearcher moSearcherIISApplicationPoolSetting = 
            	new ManagementObjectSearcher(scope, oQueryIISApplicationPoolSetting);
            ManagementObjectCollection collectionIISApplicationPoolSetting = 
            				moSearcherIISApplicationPoolSetting.Get();

            // Loop thru every object
            foreach (ManagementObject resIISApplicationPoolSetting 
            	in collectionIISApplicationPoolSetting)
            {
                // IISApplicationPoolSetting has a property called Name which will 
                // return Application Pool full name /W3SVC/AppPools/DefaultAppPool
                // Extract Application Pool Name alone using Split()
                if (resIISApplicationPoolSetting
                	["Name"].ToString().Split('/')[2] == strAppPool) 
                {
                    // IISApplicationPoolSetting has a property 
                    // called AppPoolState which has following values
                    // 2 = started 4 = stopped 1 = starting 3 = stopping
                    if (resIISApplicationPoolSetting["AppPoolState"].ToString() != "2")
                    {
                        return false;
                    }
                }
            }
            return true;
        }

代码解释

  1. System.Management 引用添加到代码中
  2. 首先,我们需要配置 WMI 的连接选项
  3. 将身份验证级别设置为 PacketPrivacy 以启用加密身份验证
  4. 根据需要,将 EnablePriviliges 设置为 true(IIS 操作不需要此设置,但在 Web 服务器高度安全的情况下,有时我们可能需要此设置)
  5. 使用 WMI 选项连接到 MicrosoftIISv2 命名空间
  6. 查询 IIS WMI 属性 IISApplicationPoolSetting,它将包含应用程序池名称及其状态
  7. 根据需要,解释属性 NameAppPoolState 以获取结果。

代码 # 2

public void performRequestedAction(String servername, String AppPoolName, String action)
        {
            StringBuilder sb = new StringBuilder();
            ConnectionOptions options = new ConnectionOptions();
            options.Authentication = AuthenticationLevel.PacketPrivacy;
            options.EnablePrivileges = true;
            ManagementScope scope = new ManagementScope(@"\\" + 
            	servername + "\\root\\MicrosoftIISv2", options);

            // IIS WMI object IISApplicationPool to perform actions on IIS Application Pool
            ObjectQuery oQueryIISApplicationPool = 
            	new ObjectQuery("SELECT * FROM IISApplicationPool");

            ManagementObjectSearcher moSearcherIISApplicationPool = 
            	new ManagementObjectSearcher(scope, oQueryIISApplicationPool);
            ManagementObjectCollection collectionIISApplicationPool = 
            	moSearcherIISApplicationPool.Get();
            foreach (ManagementObject resIISApplicationPool in collectionIISApplicationPool)
            {
                if (resIISApplicationPool["Name"].ToString().Split('/')[2] == AppPoolName)
                {
                    // InvokeMethod - start, stop, recycle can be passed as parameters as needed.
                    resIISApplicationPool.InvokeMethod(action, null);
                }
            }
        }

代码解释

  1. 在这里,我们使用 IISApplicationPool 只是为了检索应用程序池的名称并调用方法,如 startstop、根据需要回收应用程序池。
  2. 其他代码说明与上述相同
// Is any result other that started
if (!IsApplicationPoolRunning("localhost","DefaultAppPool"))
{
    // stop and start the pool
    performRequestedAction("localhost", "DefaultAppPool", "stop");
    performRequestedAction("localhost", "DefaultAppPool", "start");
}

localhost 替换为任何远程机器,并将 DefaultAppPool 替换为任何应用程序池,根据需要进行更改。

参考文献

  1. 数据包隐私和其他 DCOM 配置详细信息 - https://support.microsoft.com/en-us/kb/176799
  2. IIS WMI - https://msdn.microsoft.com/en-us/library/ms525265(v=vs.90).aspx

历史

  • 首次修订 - 2015 年 12 月 12 日
通过 C# 操作 IIS 应用程序池 - CodeProject - 代码之家
© . All rights reserved.