Question

J'ai une application C ++ qui a besoin de récupérer un IIS 7 propriétés du site (telles que les propriétés de métabase similaires à ceux IIS6 - Path, AppFriendlyName etc).

Avec IIS 7, mon code fait ceci:

  1. Obtenez le AppHostWritableAdminManager et engager le chemin MACHINE/WEBROOT/APPHOST/Default Web Site/.
  2. Appel GetAdminSection avec le appSettings de nom de la section.
  3. Ensuite, regardez la collection retournée et recherchez la propriété (Path par exemple).

Cela fonctionne dans IIS 6 mais pas sur IIS7 / 7.5.

Quels changements dois-je faire pour faire ce travail?

Était-ce utile?

La solution

Dans IIS7 les données de configuration ne sont pas stockées dans un « métabase » et aussi les propriétés de la métabase que nous sommes habitués dans IIS6 ne sont pas les mêmes. IIS7 stocke la majeure partie de ses données de configuration dans le fichier suivant:

  

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

Il existe d'autres fichiers, mais aux fins de répondre à cette question, c'est le fichier qui nous intéresse.

La documentation applicationHost.config se trouve ici:

  

<system.applicationHost> - IIS.NET
   configuration élément [IIS 7 Schéma des paramètres]
   system.applicationHost Section Groupe [IIS 7 Schéma des paramètres]

Vous pouvez trouver une liste de IIS6 métabase -> IIS7 applications de configuration XML ici:

  

Conversion des propriétés métabase des paramètres de configuration [IIS 7 ]

Par exemple, dans IIS6 le chemin vers le /root d'un site est stocké dans l'attribut Path de 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="...">

Mais dans IIS7 il est stocké différemment:

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

Cependant, si votre code doit travailler avec les deux IIS6 et IIS7 alors vous pouvez installer les composants Compatibilité avec la gestion IIS6. Cela vous permettra d'accéder aux propriétés du site IIS7 à l'aide de l'API traditionnelle IIS6 métabase tels que ADSI, System.DirectoryServices etc. La couche de compatibilité carte ces propriétés au nouveau schéma IIS7 pour vous.

La première partie de cet article explique comment installer sur Vista / Windows7 / Windows 2008:

  

Comment installer ASP.NET 1.1 avec IIS7 sur Vista et Windows 2008 - voir l'étape 1

Mise à jour:

Malheureusement C ++ n'est pas mon point fort. Cependant, je mets ensemble un exemple en C # en utilisant COM Interop pour démontrer à l'aide du 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;
}

Le code ci-dessus localise un site nommé "MySite" dans la collection <sites>. Il récupère ensuite la collection de <bindings> du site et l'impression de chaque liaisons protocol et les attributs de bindingInformation.

Votre devrait être en mesure de convertir en C ++ assez facilement.

Pour répondre à la question dans votre commentaire -

  

Par exemple, le chemin   system.applicationHost / sites créés seront   moi à la liste des sites. Y'a-t-il un   manière absolue pour arriver à mon serveur   fixations comme celle-ci (par exemple par   Faire   system.applicationHost / Sites / Default   Site Web / Liaisons

Lorsque vous utilisez le AppHostWritableAdminManager il n'y a pas un raccourci pour obtenir directement sur le site que vous souhaitez vérifier / modifier ou propriétés de elle. Dans l'exemple ci-dessus, vous verrez que je dois parcourir la collection de sites pour trouver le site que je suis intéressé. La raison est que AppHostWritableAdminManager voit tout comme des éléments et des collections d'éléments. Il est une API assez basique. Même lorsque vous utilisez l'API géré Microsoft.Web.Administration vous trouvez que si il y a des belles propriétés telles que Site.Bindings, ceux-ci sont des emballages à peine voilés autour AppHostWritableAdminManager.

En fait, si je veux trouver un site que je dois encore chercher la collection Sites soit dans une boucle ou en ajoutant un peu de sucre LINQ si j'utilise C # 3.5 ou version ultérieure:

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

La classe de base de Site est ConfigurationElement qui sous le capot enveloppe accès à IAppHostElement.

Une fois que vous avez passé un certain wrapper propriétés raccourci de base une grande partie de ce que nous faisons dans le code managé à configurer IIS (par exemple IIS FTP) est éléments, les attributs et les collections d'éléments.

Mise à jour 2:

S'il vous plaît gardez à l'esprit que je ne l'ai jamais écrit une ligne de C ++ dans ma vie. Il n'y a pas de nettoyage des chaînes ou des objets:

#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;
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top