如何确定“IIsWebDirectory”或“IIsWebVirtualDir”是否为ASP.NET应用程序?

时间:2009-03-12 21:56:19

标签: c# asp.net iis directoryservices

我目前正在编写一个C#asp.net应用程序来连接到IIS服务器并查询虚拟目录/ web目录信息。

我能够确定我应该处理的两种类型是“IIsWebDirectory”和“IIsWebVirtualDir”。

如何确定它们是否已在C#中配置为“应用程序”?

您还可以在C#和IIS herehere

中查看我的冒险经历

更新

@Kev - 我在你的回答中提取了这些信息并开发了以下简单的解决方案,以检查AppFriendlyName是否未设置为“默认应用程序”

private void CheckIfApp(DirectoryEntry de)
{
    if(de.SchemaClassName.Equals("IIsWebDirectory") || de.SchemaClassName.Equals("IIsWebVirtualDir"))
    {
        if (de.Properties["AppFriendlyName"].Value != null)
        {
            string friendlyName = de.Properties["AppFriendlyName"].Value.ToString();

            if (!friendlyName.Equals("Default Application"))
            {
                //do something...
            }
        }
    }
}

1 个答案:

答案 0 :(得分:8)

有三种方法可以解决这个问题:

  • 普通的旧System.DirectoryServices
  • 解析IIS metabase.xml文件
  • System.DirectoryServices和一些COM 互操作

普通的旧System.DirectoryServices

确定将IIsWebDirectoryIIsWebVirtualDir IIS管理对象配置为仅使用System.DirectoryServices的应用程序有时可能是一项非显而易见的业务,因为元数据库属性继承。

例如,当您创建“应用程序”时,通常会在IIsWebDirectoryIIsWebVirtualDir配置数据库管理对象上设置三个属性 -

AppFriendlyName
AppIsolated
AppRoot

在元数据库中,您会看到如下内容:

<!-- This is an application -->
<IIsWebVirtualDir   Location ="/LM/W3SVC/1/ROOT/MyApp"
    AccessFlags="AccessRead | AccessScript"
    AppFriendlyName="MyAppKev"
    AppIsolated="2"
    AppRoot="/LM/W3SVC/1/Root/MyApp"    
    >
</IIsWebVirtualDir>

现在你会认为它就像检查这三个属性的存在一样简单,特别是AppIsolated属性,因为这是用于指示应用程序隔离类型的属性(进程内[0] ],进程外[1]或汇集[2]) - 每个应用程序都需要此属性。作为旁注,在运行IIS6的服务器上,如果IIS在IIS5兼容模式下运行,则只会看到AppIsolated=0|1。创建自己的应用程序时,应始终设置AppIsolated=2,这意味着站点或应用程序将在您的一个应用程序池(w3wp.exe)中运行。

无论如何......由于配置数据库属性继承,检查上面列出的三个属性中的任何一个并不能保证您正在检查的对象实际上是一个应用程序 - 无论是使用ADSI,WMI还是{{1 API的。即使您正在检查的对象只是一个虚拟目录(而不是应用程序),您仍将获得返回的值,因为它们将从父应用程序继承。

例如,如果DirectoryServices是位于默认网站中的虚拟目录(非应用程序),您仍会看到/MyVdir的值,这是因为它是从{{1}继承的})。这同样适用于AppIsolatedIIS://Localhost/w3svc/1/root属性。

我在这里采用的方法是将AppFriendlyName属性与目标管理对象上的AppRoot属性进行比较。 DirectoryEntry.Path是一个属性,用于指示特定应用程序的根目录。如果您正在检查站点的配置数据库层次结构深处的IIS管理对象,并且您需要知道其应用程序的根源,这可能很方便。

所以,我说应用程序位于:

AppRoot

...并说我们有一个AppRoot的实例:

IIS://Localhost/w3svc/1/root/MyApp

DirectoryEntry属性设置为DirectoryEntry de = new DirectoryEntry("IIS://Localhost/w3svc/1/root/MyApp"); de.Path管理对象属性IIS://Localhost/w3svc/1/root/MyApp将设置为AppRoot。您需要做的就是去除前导de.Properties["AppRoot"].Value/LM/W3SVC/1/Root/MyApp字符串,并进行不区分大小写的字符串比较。如果匹配则该路径上的对象是应用程序。

解析IIS metabase.xml文件

我过去曾使用另一种方式作为死服务器重建工作的一部分,我们有配置数据库文件,我们知道我们创建的vdirs和应用程序的数据库表,而不是其他 - 服务器弹出前有1200个网站和众多虚拟目录和应用程序。基本上我将整个IIS://Localhost文件加载到/LM。然后我使用XPath查找metabase.xml属性的存在,其中XMLDocument属性与我感兴趣的路径匹配。

这是代码的摘录,应该为您提供该想法的一般要点:

AppIsolated

只要没有很高的应用程序/虚拟目录转换,解析原始Location文件就可以了。这是因为内存中的元数据库更新不会立即刷新到private XmlNamespaceManager _nsm = new XmlNamespaceManager(new NameTable()); private XmlDocument _doc = new XmlDocument(); _doc.Load(@"c:\windows\system32\inetsrv\metabase.xml"); _nsm.AddNamespace("iis", "urn:microsoft-catalog:XML_Metabase_V64_0"); // lmPath could be build from the DirectoryEntry.Path property string lmPath = "/lm/w3svc/1/root/myapp"; // Try as an IIsWebDirectory object string iisWebDirectoryXPath = String.Format(@"//iis:IIsWebDirectory[translate(@Location, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz') = '{0}']", lmPath); mbNode = _doc.DocumentElement.SelectSingleNode(iisWebDirectoryXPath, _nsm); if(mbNode != null) { // We found an IIsWebDirectory - is it an application though? if (mbNode.Attributes["AppIsolated"] != null) { // IIsWebDirectory is an Application } } else { // Is our object an IIsWebVirtualDir? string iisWebVirtualDirectoryXPath = String.Format(@"//iis:IIsWebVirtualDir[translate(@Location, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz') = '{0}']", lmPath); mbNode = _doc.DocumentElement .SelectSingleNode(iisWebVirtualDirectoryXPath, _nsm); if (mbNode != null) { // Yes it's an IIsWebVirtualDir if (mbNode.Attributes["Path"] != null) { if(mbNode.Attributes["AppIsolated"] != null) { // And it's an application } } } } 文件。我不建议这样做,我只是出于系统恢复的目的这样才解决问题。

System.DirectoryServices和一些COM互操作

最后还有第三种方式(可能是最简单的),如果您的开发PC没有运行IIS6 / Windows 2003,您可能无法正常测试(我没有可用的XP机器来验证这是否有效)用IIS 5.1)。您所做的是添加对名为“Active DS IIS Extension Dll”(metabase.xml)的COM库的引用,它在Visual Studio的“添加引用”对话框的COM选项卡上列出。添加此引用时,Visual Studio还将自动解析并引用依赖项“Active DS Type Library”(metabase.xml)。在您的解决方案参考文件夹中,您会看到它们被列为“ActiveDS”和“IISExt”。

使用“Active DS IIS Extension”库,我们可以通过执行以下操作来测试特定路径上的IIS管理对象是否实际上是IIS应用程序:

%systemroot%\system32\inetsrv\iisext.dll

使用WMI还有第四种方法,但我只是在水中蘸了一些相当简单的IIS / App Pool管理任务。