2011-01-22 61 views
3

我有一個C++應用程序需要檢索IIS 7站點的屬性(例如類似於IIS6中的元數據庫屬性 - Path,AppFriendlyName等)。獲取IIS 7站點屬性

使用IIS 7,我的代碼做到這一點:

  1. 獲取AppHostWritableAdminManager並提交路徑MACHINE/WEBROOT/APPHOST/Default Web Site/
  2. 致電GetAdminSection,部分名稱爲appSettings
  3. 然後查看返回的集合並查找屬性(例如,Path)。

這適用於IIS 6,但不適用於IIS7/7.5。

爲了完成這項工作我需要做些什麼改變?

回答

8

在IIS7中,配置數據未存儲在「元數據庫」中,而且我們在IIS6中習慣使用的元數據庫屬性也不相同。 IIS7存儲在以下文件批量其配置數據:

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

還有其他的文件,但對回答這個問題的目的,這是我們感興趣的文件。

applicationHost.config的文檔可以在這裏找到:

<system.applicationHost> - IIS.NET
configuration Element [IIS 7 Settings Schema]
system.applicationHost Section Group [IIS 7 Settings Schema]

你可以找到IIS6元數據庫的清單 - 在這裏> IIS7 XML配置映射:

Converting Metabase Properties to Configuration Settings [IIS 7]

例如在IIS6的路徑網站的/root存儲在IIsWebVirtualDirPath屬性中。即:

<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管理兼容性組件。這將允許您使用傳統IIS6元數據庫API(如ADSI,System.DirectoryServices等)訪問IIS7站點屬性。兼容性層將爲您映射這些屬性到新的IIS7模式。

這篇文章的第一部分介紹瞭如何在Vista/Windows7的/ Windows 2008的安裝此:

How to install ASP.NET 1.1 with IIS7 on Vista and Windows 2008 - see step #1

更新:

不幸的是C++是不是我的優點。不過,我使用COM互操作使用AppHostWritableAdminManager證明放在一起的例子在C#:

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

上面的代碼位於一個在<sites>集合在一個名爲「mysite的」網站。然後它檢索該網站的<bindings>集合和打印的每個綁定和bindingInformation屬性。

你應該能夠很容易地將其轉換爲C++。

要回答這個問題在您的評論 -

例如,路徑 system.applicationHost /網站將得到 我的站點列表。是否有 絕對的方式通過 要到我的服務器 綁定像這樣(例如做 system.applicationHost /網站/默認 網站/綁定

當使用AppHostWritableAdminManager沒有快捷方式直接訪問您想要檢查/修改的網站或它的屬性在上面的例子中,您會看到我需要循環訪問網站集以查找我感興趣的網站。原因是AppHostWritableAdminManager將一切看作元素和元素集合,它是一個相當基礎的API,即使使用受管理的API,您也會發現雖然有一些不錯的屬性例如Site.Bindings,這些都是圍繞AppHostWritableAdminManager的簡單僞裝包裝。

事實上,如果我想,如果我使用C#3.5或更高版本找到一個網站,我還是要搜索Sites收集無論是在for循環或通過添加一些LINQ糖:

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; 
} 
+0

Kev,非常感謝您的回覆。你可以請我參考「管理部分」的解釋和提交路徑?例如,路徑system.applicationHost/Sites將讓我訪問站點列表。有沒有一種絕對的方式來到我的服務器綁定這樣(例如通過做system.applicationHost /站點/默認網站/綁定? – Ron

+0

@龍 - 請參閱我的更新的答案。希望這將清除事情。 – Kev

+0

再次感謝 - 我想我已經開始想到了這一點,基本上,爲了訪問我的服務器綁定,我需要在system.applicationHost/Sites部分找到我的網站,然後遍歷集合並找到我的網站,然後,我需要迭代我的網站的子元素,並尋找綁定。這很好,但有沒有辦法直接到綁定(可能是像system.applicationHost /默認網站/綁定?請讓我知道你的想法 - 並感謝如此多的 – Ron