Получение свойств сайта IIS 7 - PullRequest
3 голосов
/ 22 января 2011

У меня есть приложение C ++, которому нужно получить свойства сайта IIS 7 (такие как свойства метабазы, аналогичные свойствам в IIS6 - Path, AppFriendlyName и т. Д.).

С IIS 7 мой код делает это:

  1. Получите AppHostWritableAdminManager и зафиксируйте путь MACHINE/WEBROOT/APPHOST/Default Web Site/.
  2. Позвоните GetAdminSection с названием секции appSettings.
  3. Затем посмотрите на возвращенную коллекцию и найдите свойство (например, Path).

Это работает в IIS 6, но не в IIS7 / 7.5.

Какие изменения мне нужно внести, чтобы сделать эту работу?

1 Ответ

8 голосов
/ 23 января 2011

В IIS7 данные конфигурации не хранятся в «метабазе», а также свойства метабазы, к которым мы привыкли в IIS6, не совпадают. IIS7 хранит большую часть своих данных конфигурации в следующем файле:

%systemroot%\System32\InetSrv\Config\applicationHost.config

Есть и другие файлы, но для ответа на этот вопрос нам нужен этот файл.

Документацию для applicationHost.config можно найти здесь:

<system.applicationHost> - IIS.NET
Элемент конфигурации [Схема настроек IIS 7]
system.applicationHost Группа разделов [Схема настроек IIS 7]

Список метабазы ​​IIS6 -> IIS7 XML можно найти здесь:

Преобразование свойств метабазы ​​в настройки конфигурации [IIS 7]

Например, в IIS6 путь к /root сайта хранится в атрибуте Path IIsWebVirtualDir. i.e.:

<IIsWebServer Location="/LM/W3SVC/67793744" AuthFlags="0" ServerAutoStart="TRUE" 
              ServerBindings="217.69.47.170:80:app2.dev" ServerComment="app2" /> 
<IIsWebVirtualDir Location="/LM/W3SVC/67793744/root" 
    AccessFlags="AccessRead | AccessScript" 
    AppFriendlyName="Default Application" 
    AppIsolated="2" 
    AppRoot="/LM/W3SVC/67793744/Root" 
    AuthFlags="AuthAnonymous | AuthNTLM" 
    DirBrowseFlags="DirBrowseShowDate | DirBrowseShowTime | DirBrowseShowSize |
            DirBrowseShowExtension | DirBrowseShowLongDate | EnableDefaultDoc" 
    Path="D:\websites\ssl-test\www\kerboom" 
    ScriptMaps="...">

Но в IIS7 он хранится по-другому:

<sites>
    <site name="Default Web Site" id="1" serverAutoStart="true">
        <!-- this is the functional equivalent of the /root app in IIS6 -->
        <application path="/">
            <virtualDirectory path="/" 
                              physicalPath="%SystemDrive%\inetpub\wwwroot" />
        </application>
    </site>
<sites>

Однако, если ваш код должен работать как с IIS6, так и с IIS7, вы можете установить компоненты IIS6 Management Compatibility. Это позволит вам получить доступ к свойствам сайта IIS7 с помощью традиционных API метабазы ​​IIS6, таких как ADSI, System.DirectoryServices и т. Д. Уровень совместимости сопоставит эти свойства с новой для вас схемой IIS7.

В первой части этой статьи объясняется, как установить ее в Vista / Windows7 / Windows 2008:

Как установить ASP.NET 1.1 с IIS7 в Vista и Windows 2008 - см. Шаг # 1

Обновление:

К сожалению, C ++ не является моей сильной стороной. Однако я собрал пример в C # с использованием COM Interop для демонстрации использования AppHostWritableAdminManager:

IAppHostWritableAdminManager wam = new AppHostWritableAdminManager();
IAppHostElement sites = 
   wam.GetAdminSection("system.applicationHost/sites", "MACHINE/WEBROOT/APPHOST");
IAppHostElementCollection sitesCollection = sites.Collection;

long index = FindSiteIndex(sitesCollection, "MySite");
if(index == -1) throw new Exception("Site not found");

IAppHostElement site = sitesCollection[index];
IAppHostElementCollection bindings = site.ChildElements["bindings"].Collection;

for (int i = 0; i < bindings.Count; i++)
{
  IAppHostElement binding = bindings[i];
  IAppHostProperty protocolProp = binding.GetPropertyByName("protocol");
  IAppHostProperty bindingInformationProp = 
      binding.GetPropertyByName("bindingInformation");

  string protocol = protocolProp.Value;
  string bindingInformation = bindingInformationProp.Value;

  Debug.WriteLine("{0} - {1}", protocol, bindingInformation);

}

static long FindSiteIndex(IAppHostElementCollection sites, string siteName)
{
  for (int i = 0; i < sites.Count; i++)
  {
    IAppHostElement site = sites[i];
    Debug.WriteLine(site.Name);
    IAppHostProperty prop = site.GetPropertyByName("name");
    if(prop.Value == siteName)
    {
      return i;
    }
  }
  return -1;
}

Приведенный выше код находит сайт с именем «MySite» в коллекции <sites>. Затем он извлекает коллекцию <bindings> сайта и распечатывает все привязки protocol и bindingInformation атрибутов.

Вы должны легко преобразовать это в C ++.

Чтобы ответить на вопрос в вашем комментарии -

Например, путь system.applicationHost / сайты получат меня к списку сайтов. Есть абсолютный способ попасть на мой сервер такие привязки (например, дела system.applicationHost / Сайты / Default Веб-сайт / Привязки

При использовании AppHostWritableAdminManager нет быстрого доступа к сайту, который вы хотите проверить / изменить, или его свойствам. В приведенном выше примере вы увидите, что мне нужно пройтись по семейству сайтов, чтобы найти интересующий меня сайт. Причина этого в том, что AppHostWritableAdminManager видит все как элементы и коллекции элементов. Это довольно простой API. Даже при использовании управляемого Microsoft.Web.Administration API вы обнаружите, что, хотя есть некоторые приятные свойства, такие как Site.Bindings, это тонко замаскированные оболочки вокруг AppHostWritableAdminManager.

На самом деле, если я хочу найти сайт, мне все равно придется искать коллекцию Sites либо в цикле for, либо путем добавления сахара LINQ, если я использую C # 3.5 или более позднюю версию:

using(ServerManager serverManager = new ServerManager())
{
    Site x = serverManager.Sites.FirstOrDefault(s => s.Name == "MySite");
}

Site базовый класс ConfigurationElement, который под капотом оборачивает доступ к IAppHostElement.

Когда вы ознакомитесь с некоторыми основными свойствами оболочки ярлыков, большая часть того, что мы делаем в управляемом коде для настройки IIS (например, IIS FTP), - это элементы, атрибуты и наборы элементов.

Обновление 2:

Пожалуйста, имейте в виду, что я никогда не писал строки C ++ в своей жизни. Там нет очистки строк или объектов:

#include "stdafx.h"
#include <windows.h>
#include <stdio.h>
#include <ahadmin.h>
#include <crtdbg.h>

static IAppHostElement* 
   FindSite(IAppHostElementCollection *pCollection, BSTR bstrSiteName);

int _tmain(int argc, _TCHAR* argv[])
{
  CoInitialize(NULL);

  IAppHostWritableAdminManager *pMgr = NULL;
  IAppHostElement *pElem = NULL;
  IAppHostElementCollection *pSitesCollection = NULL;
  IAppHostElement *pSite = NULL;
  IAppHostElement *pBindings = NULL;
  IAppHostElement *pBinding = NULL;
  IAppHostElementCollection *pBindingsCollection = NULL;
  IAppHostChildElementCollection *pChildElements = NULL;
  IAppHostProperty *pProtocol = NULL;
  IAppHostProperty *pBindingInformation = NULL;

  BSTR bstrSectionName = SysAllocString( L"system.applicationHost/sites" );
  BSTR bstrConfigCommitPath = SysAllocString( L"MACHINE/WEBROOT/APPHOST" );
  BSTR bstrSiteName = SysAllocString( L"MySite" );
  BSTR bstrBindingsConst = SysAllocString( L"bindings" );
  BSTR bstrBindingProtocol = SysAllocString( L"protocol" );
  BSTR bstrBindingInformation = SysAllocString( L"bindingInformation" );

  VARIANT vtPropertyName;
  VARIANT vtIndex;

  HRESULT hr = S_OK;

  hr = CoCreateInstance( __uuidof(AppHostWritableAdminManager), NULL, 
      CLSCTX_INPROC_SERVER, __uuidof(IAppHostWritableAdminManager), (void**) &pMgr);

  hr = pMgr->GetAdminSection(bstrSectionName, bstrConfigCommitPath, &pElem);
  hr = pElem->get_Collection(&pSitesCollection);

  pSite = FindSite(pSitesCollection, bstrSiteName);

  hr = pSite->get_ChildElements(&pChildElements);

  vtPropertyName.vt = VT_BSTR;
  vtPropertyName.bstrVal = bstrBindingsConst;

  hr = pChildElements->get_Item(vtPropertyName, &pBindings);
  hr = pBindings->get_Collection(&pBindingsCollection);

  DWORD bindingsCount;
  hr = pBindingsCollection->get_Count(&bindingsCount);

  for(int i = 0; i < bindingsCount; i++)
  {
    vtIndex.lVal = i;
    vtIndex.vt = VT_I4;
    hr = pBindingsCollection->get_Item(vtIndex, &pBinding);

    hr = pBinding->GetPropertyByName(bstrBindingProtocol, &pProtocol);
    hr = pBinding->GetPropertyByName(bstrBindingInformation, &pBindingInformation);

    BSTR bstrProtocol;
    BSTR bstrBindingInformation;

    hr = pProtocol->get_StringValue(&bstrProtocol);
    hr = pBindingInformation->get_StringValue(&bstrBindingInformation);

    _tprintf(_T("Protocol: %s, BindingInfo: %s\n"), bstrProtocol, bstrBindingInformation);
  }

  CoUninitialize();
  return 0;
}

IAppHostElement* FindSite(IAppHostElementCollection *pCollection, BSTR bstrSiteName)
{
  DWORD count = -1;
  pCollection->get_Count(&count);

  BSTR bstrPropName = SysAllocString( L"name");

  for(DWORD i = 0; i < count; i++)
  {
    IAppHostElement *site = NULL;
    IAppHostProperty *prop = NULL;
    BSTR bstrPropValue;

    HRESULT hr = S_OK;

    VARIANT vtCount;
    VariantInit(&vtCount);
    vtCount.lVal = i;
    vtCount.vt = VT_I4;

    hr = pCollection->get_Item(vtCount, &site);
    hr = site->GetPropertyByName(bstrPropName, &prop);
    hr = prop->get_StringValue(&bstrPropValue);

    if(wcscmp(bstrPropValue, bstrSiteName) == 0)
    {
      return site;
    }
  }

  return NULL;
}
...