Вопрос

У меня есть приложение на 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.

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

Это было полезно?

Решение

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

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

Существуют и другие файлы, но для того, чтобы ответить на этот вопрос, это тот файл, который нас интересует.

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

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

Вы можете найти список сопоставлений XML-конфигурации метабазы IIS6 -> IIS7 здесь:

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

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

<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.Это позволит вам получить доступ к свойствам сайта IIS7 с использованием традиционных API метабазы IIS6, таких как ADSI, System.DirectoryServices и т.д.Уровень совместимости сопоставит эти свойства с новой схемой IIS7 для вас.

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

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

Обновить:

К сожалению, C ++ не является моей сильной стороной.Однако я собрал пример на C # с использованием COM-взаимодействия, чтобы продемонстрировать использование 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/Sites приведет меня к списку сайтов.Есть ли абсолютный способ добраться до моего сервера привязки, подобные этой (например, выполнив system.applicationHost /Sites /Default Веб-сайт / Привязки

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

На самом деле, если я хочу найти сайт, мне все равно придется искать Sites сбор либо в цикле for, либо путем добавления некоторого количества LINQ sugar, если я использую 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;
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top