IIS ネイティブ HTTP モジュールは設定を Web.config から読み込むのが一般的ですが、どうやって読み込むのか分からなかったので調べました。ネイティブ HTTP モジュールの作り方は以前に書いた通りです。
Web.config の読み込みは IHttpServer から IAppHostAdminManager を取得し、さらに GetAdminSection メソッドを呼び出すと、該当する Web.config のセクションを読み込めます。
IAppHostAdminManager::GetAdminSection Method
言葉だと説明にしくいので、実際に動くコードを使って紹介します。
設定を読み込む
IHttpContext から MetaPath を取得し、GetAdminSection メソッドを呼び出す流れです。IAppHostElement を取得出来れば楽ですが、COM なので BSTR を使ったり、Release を忘れないようにするなど面倒です。
HRESULT CModuleConfiguration::Initialize(IN IHttpContext *pHttpContext, IN IHttpServer *pHttpServer) { // samplecfg 要素を読み込む IAppHostElement *section; BSTR path = SysAllocString(pHttpContext->GetMetadata()->GetMetaPath()); BSTR sectionPath = SysAllocString(L"system.webServer/samplecfg"); pHttpServer->GetAdminManager()->GetAdminSection(sectionPath, path, §ion); SysFreeString(sectionPath); SysFreeString(path); if (section == NULL) { return S_OK; } // samplecfg.config 属性を読み込む IAppHostProperty property; BSTR propertyName = SysAllocString(L"config"); section->GetPropertyByName(propertyName, &property); SysFreeString(propertyName); // プロパティの値を読み込む BSTR propertyValue; property->get_StringValue(&propertyValue); SysFreeString(propertyValue); // リソースを解放 property->Release(); section->Release(); return S_OK; }
IAppHostAdminManager の取得に必要な IHttpServer は RegisterModule 関数でしか取れないので、そのタイミングでグローバルな領域にでも保存しておく必要があります。
あとは IHttpContext も必要になるので、呼び出されるタイミングには気を使う必要があります。
COM スマートポインタを使う
Visual C++ の COM スマートポインタを使うと、リソースの解放を考えずに書けるので便利です。
COM スマートポインタを使うには comdef.h をインクルードして、_COM_SMARTPTR_TYPEDEF を使って該当する COM インターフェースを定義しておく必要があります
#include <comdef.h> _COM_SMARTPTR_TYPEDEF(IAppHostElement, __uuidof(IAppHostElement)); _COM_SMARTPTR_TYPEDEF(IAppHostProperty, __uuidof(IAppHostProperty)); static const _bstr_t sectionPath = L"system.webServer/samplecfg"; static const _bstr_t propertyName = L"config"; HRESULT CModuleConfiguration::Initialize(IN IHttpContext *pHttpContext, IN IHttpServer *pHttpServer) { // samplecfg 要素を読み込む IAppHostElementPtr section; _bstr_t path = pHttpContext->GetMetadata()->GetMetaPath(); pHttpServer->GetAdminManager()->GetAdminSection(sectionPath, path, §ion); if (section == NULL) { return S_OK; } // samplecfg.config 属性の値を読み込む IAppHostPropertyPtr property; section->GetPropertyByName(propertyName, &property); _bstr_t propertyValue; property->get_StringValue(&propertyValue.GetBSTR()); return S_OK; }
_com_ptr_t と _bstr_t を使うと解放する必要が無いので、とてもシンプルに書けました。_bstr は comutil.h だけで使えますが、_COM_SMARTPTR_TYPEDEF は comdef.h が必要なので注意です。
COM リソースの解放を忘れると IIS のワーカープロセスが終了しなくなるようでした。