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 のワーカープロセスが終了しなくなるようでした。