Как определить, является ли «IIsWebDirectory» или «IIsWebVirtualDir» приложением ASP.NET? - PullRequest
5 голосов
/ 13 марта 2009

В настоящее время я пишу приложение на C # asp.net для подключения к серверу IIS и запроса информации о виртуальном каталоге / веб-каталоге.

Я могу определить, что есть два типа, с которыми мне приходится иметь дело, это «IIsWebDirectory» и «IIsWebVirtualDir».

Как определить, настроены ли они как «приложение» в C #?

Вы также можете просмотреть мои приключения в C # и IIS здесь и здесь

UPDATE

@ 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 Ответ

8 голосов
/ 13 марта 2009

Существует три способа решения этой проблемы:

  • Обычная старая System.DirectoryServices
  • Разбор файла IIS metabase.xml
  • System.DirectoryServices и некоторые COM Interop

Обычная старая System.DirectoryServices

Определение того, настроен ли IIsWebVirtualDir или *1016* объект администрирования IIS как приложение, использующее только System.DirectoryServices, иногда может быть неочевидным делом из-за наследования свойства метабазы.

Например, когда вы создаете «приложение», обычно для объектов администрирования метабазы ​​IIsWebDirectory или IIsWebVirtualDir обычно устанавливаются три свойства -

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, потому что это свойство используется для указания типа изоляции приложения (in-process [0], вне процесса [1] или в виде пула [2]) - и каждому приложению требуется это свойство. В качестве идентификатора на сервере под управлением IIS6 вы увидите AppIsolated=0|1, только если IIS работает в режиме совместимости с IIS5. Когда вы создаете свои собственные приложения, вы всегда должны устанавливать AppIsolated=2, что означает, что сайт или приложение будут работать в одном из ваших пулов приложений (w3wp.exe).

В любом случае ... из-за наследования свойства метабазы ​​проверка любого из трех свойств, перечисленных выше, не гарантирует, что исследуемый объект действительно является приложением - будь то с использованием ADSI, WMI или DirectoryServices API. Даже если проверяемый вами объект является просто виртуальным каталогом (а не приложением), вы все равно получите возвращаемые значения, поскольку они будут унаследованы от родительского приложения.

Например, если /MyVdir является виртуальным каталогом (не приложением), расположенным на веб-сайте по умолчанию, вы все равно увидите значение для AppIsolated, так как оно унаследовано от IIS://Localhost/w3svc/1/root). То же самое относится к свойствам AppFriendlyName и AppRoot.

Подход, который я здесь использовал, заключался в сравнении свойства DirectoryEntry.Path со свойством AppRoot в целевом объекте admin. AppRoot - это свойство, которое указывает, где находится конкретное приложение. Это может быть удобно, если вы изучаете объект администрирования IIS в глубине иерархии метабазы ​​сайта и вам необходимо знать, где находится его приложение.

Итак, скажем, у меня есть приложение, расположенное по адресу:

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 admin, de.Properties["AppRoot"].Value будет установлено значение /LM/W3SVC/1/Root/MyApp. Все, что вам нужно сделать, это удалить ведущие строки IIS://Localhost и /LM и выполнить сравнение строк без учета регистра. Если есть совпадение, тогда объект по этому пути является приложением.

Анализ файла IIS metabase.xml

В прошлом я использовал другой способ, как часть работы по восстановлению мертвого сервера, где у нас был файл метабазы, таблица базы данных vdirs и приложений, которые, как мы знали, мы создали, и ничего более - сервер было 1200 веб-сайтов и множество виртуальных каталогов и приложений, прежде чем он появился. Я загрузил весь файл metabase.xml в XMLDocument. Затем я использовал XPath для поиска атрибута 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
            }
        }
    }
}

Разбор необработанного файла metabase.xml работает нормально, пока не происходит большой оборот приложений / виртуальных каталогов. Это связано с тем, что обновления метабазы ​​в памяти не сразу сбрасываются в файл metabase.xml. Я бы не советовал делать это, я только подходил к этой проблеме исключительно для целей восстановления системы.

System.DirectoryServices и некоторые COM-взаимодействия

Наконец, есть третий способ (и, возможно, самый простой), который вы не сможете протестировать должным образом, если ваш компьютер для разработки не работает под управлением IIS6 / Windows 2003 (у меня нет машины XP, чтобы проверить, работает ли она с IIS 5.1). Вы добавляете ссылку на библиотеку COM под названием «Active DS IIS Extension Dll» (%systemroot%\system32\inetsrv\iisext.dll), она указана на вкладке COM в диалоговом окне «Добавить ссылку» в Visual Studio. При добавлении этой ссылки Visual Studio также автоматически разрешает и ссылается на зависимость «Active DS Type Library» (%systemroot%\system32\activeds.tlb). В папке с ссылками на решения вы увидите их в списке «ActiveDS» и «IISExt».

Используя библиотеку «Active DS IIS Extension», мы можем проверить, действительно ли объект администратора IIS по определенному пути является приложением IIS, выполнив следующие действия:

using (DirectoryEntry de = 
        new DirectoryEntry("IIS://Localhost/w3svc/1/root/MyApp"))
{
    // Cast our native underlying object to the correct interface
    IISExt.IISApp2 app = (IISExt.IISApp2)de.NativeObject;
    int status = app.AppGetStatus2();

    switch(status)
    {
        case 0:
            Console.WriteLine("It's an app but it's stopped.");
            break;

        case 1:
            Console.WriteLine("It's an app and it's running.");
            break;

        case 2:
            Console.WriteLine("No application found here.");
            break;
    }

}

Существует четвертый способ использования WMI, но я лишь опускаю пальцы в воду для некоторых довольно простых задач управления IIS / App Pool.

...