Pregunta

Tengo un C ++ aplicación que necesita recuperar un IIS 7 propiedades de sitio (tales como propiedades de la metabase similares a las de IIS6 - Path, AppFriendlyName etc).

Con IIS 7, mi código hace lo siguiente:

  1. Obtener el AppHostWritableAdminManager y cometer el MACHINE/WEBROOT/APPHOST/Default Web Site/ camino.
  2. GetAdminSection llamada con el nombre de sección appSettings.
  3. A continuación, mira el colección devuelta y el aspecto de la propiedad (Path por ejemplo).

Esto funciona de IIS 6, pero no en IIS 7 / 7.5.

¿Qué cambios necesito hacer con el fin de hacer este trabajo?

¿Fue útil?

Solución

En IIS7 los datos de configuración no se almacena en un "metabase" y también las propiedades de la metabase que estamos acostumbrados en IIS6 no son lo mismo. almacena IIS7 la mayor parte de sus datos de configuración en el archivo siguiente:

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

Hay otros archivos, pero a los efectos de responder a esta pregunta, esta es la imagen que nos interesa.

La documentación para applicationHost.config se puede encontrar aquí:

<system.applicationHost> - IIS.NET
configuration Element [IIS 7 Configuración del esquema]
system.applicationHost Sección Group [IIS 7 Configuración del esquema]

Se puede encontrar una lista de IIS6 metabase -> IIS7 configuración XML asignaciones aquí:

conversión de propiedades de la metabase a los valores de configuración [IIS 7 ]

Por ejemplo, en IIS6 la ruta a /root de un sitio se almacena en el atributo Path de IIsWebVirtualDir. es decir:.

<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="...">

Pero en IIS7 se almacena de forma diferente:

<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>

Sin embargo, si su código debe trabajar tanto con IIS6 y IIS7 entonces usted puede instalar los componentes de IIS 6 Compatibilidad con la administración. Esto le permitirá a las propiedades del sitio de acceso usando IIS7 tradicional como ADSI, System.DirectoryServices etc. La capa de compatibilidad trazará un mapa de estas propiedades al nuevo esquema IIS7 para usted.

API IIS6 metabase

La primera parte de este artículo se explica cómo instalar esto en Vista / Windows 7 / Windows 2008:

Cómo instalar ASP.NET 1.1 con IIS 7 en Windows Vista y Windows 2008 - vea el paso # 1

Actualización:

Desafortunadamente C ++ no es mi punto fuerte. Sin embargo puse juntos un ejemplo en C # usando interoperabilidad COM para demostrar el uso de la 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;
}

El código anterior localiza un sitio denominado "Mi sitio" en la colección <sites>. A continuación, recupera la colección <bindings> del sitio y de impresión de cada fijaciones protocol y atributos bindingInformation.

Su debe ser capaz de convertir esto en C ++ con bastante facilidad.

Para responder a la pregunta en su comentario -

Por ejemplo, el camino system.applicationHost / Sitios conseguirá me a la lista de sitios. Hay un manera más favorable para llegar a mi servidor fijaciones como este (por ejemplo por haciendo system.applicationHost / sites / default Sitio web / Vinculaciones

Cuando se utiliza el AppHostWritableAdminManager no hay un acceso directo para obtener directamente al sitio que desea inspeccionar / o modificar sus propiedades. En el ejemplo anterior, se verá que tengo que recorrer la colección sitios para encontrar el sitio que me interesa. La razón de esto es que AppHostWritableAdminManager ve todo como elementos y colecciones de elementos. Es una API bastante básico. Incluso cuando se utiliza la API Microsoft.Web.Administration conseguido a encontrar que, si bien hay algunas propiedades agradables como Site.Bindings, estos son envolturas alrededor AppHostWritableAdminManager escasamente disimulada.

De hecho, si quiero encontrar un sitio que todavía tengo que buscar en la colección Sites ya sea en un bucle for o añadiendo un poco de azúcar LINQ si estoy usando C # 3.5 o posterior:

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

clase base de Site es ConfigurationElement que bajo el capó envuelve el acceso a IAppHostElement.

Una vez que esté más allá de algunas propiedades de acceso directo básica envoltorio gran parte de lo que hacemos en código administrado para configurar IIS (por ejemplo FTP de IIS) es elementos, atributos y colecciones de elementos.

Actualización 2:

Por favor, tenga en cuenta que nunca he escrito una línea de C ++ en mi vida. No hay limpieza de cadenas u objetos:

#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;
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top