チュートリアル: ネイティブ コードを使用したGlobal-Level HTTP モジュールの作成
このチュートリアルでは、C++ を使用して、IIS 7 で新しい要求処理アーキテクチャを実装するサンプルのグローバル レベル HTTP モジュールを作成する方法を示します。 この新しいアーキテクチャは、以前のバージョンの ASP.NET HTTP モジュールと ISAPI フィルターまたは拡張機能を使用して IIS アプリケーションを記述する場合に、ネイティブ コード プログラミングの機能を拡張します。 新しい要求処理アーキテクチャを使用した HTTP モジュールの設計の詳細については、「 Native-Code HTTP モジュールの設計」を参照してください。
このチュートリアルでは、HTTP モジュール用の C++ プロジェクトを作成し、"Hello World" プロジェクトに必要なコードを追加してから、モジュールをコンパイルしてテストします。
必須コンポーネント
この例の手順を完了するには、次のソフトウェアが必要です。
IIS 7。
Visual Studio 2005:
注意
Visual Studio .NET 2003 以前を使用することもできますが、チュートリアルの手順は同じではない可能性があります。
モジュールの作成
チュートリアルのこの部分では、HTTP モジュール用に空の C++ DLL プロジェクトを作成します。
新しい C++ DLL プロジェクトを作成するには
Visual Studio 2005 を起動します。
グローバル オプションに SDK インクルード ファイルへの適切なパスがすべて含まれることを確認します。
[ツール] メニューの [オプション] をクリックします。
ツリー ビューで [ プロジェクトとソリューション] ノードを展開し、[ VC++ ディレクトリ] をクリックします。
[ ディレクトリを表示する] ドロップダウン ボックスで、[ ファイルを含める] を選択します。
SDK インクルード ファイルをインストールしたパスが一覧表示されていることを確認します。 パスが一覧にない場合は、[ 改行 ] アイコンをクリックし、SDK インクルード ファイルをインストールしたパスを追加します。
[OK] をクリックします。
新しい C++ プロジェクトを作成します。
[ファイル] メニューの [新規作成] をポイントし、 [プロジェクト] をクリックします。
[新しいプロジェクト] ダイアログ ボックスが表示されます。
[ プロジェクトの種類 ] ウィンドウで、[ Visual C++ ] ノードを展開し、[ Win32] をクリックします。
[テンプレート] ウィンドウ で 、[ Win32 プロジェクト] を選択します。
[ 名前 ] ボックスに 「HelloWorld」と入力します。
[ 場所 ] ボックスに、サンプルのパスを入力します。
[OK] をクリックします。
Win32 アプリケーション ウィザードが開きます。
[ アプリケーションの設定] をクリックします。
[ アプリケーションの種類] で、[ DLL] をクリックします。
[ その他のオプション] で、[ プロジェクトを空にする] をクリックします。
[完了] をクリックします。
コード ファイルとソース ファイルの追加
次の手順では、必要な C++ ファイルとモジュール定義ファイルをプロジェクトに追加します。
ソース ファイルをプロジェクトに追加するには
RegisterModule 関数をエクスポートするモジュール定義ファイルを作成します。
ソリューション エクスプローラーで、[ソース ファイル] を右クリックし、[追加] をポイントして、[新しい項目] をクリックします。
[新しい項目の追加] ダイアログ ボックスが開きます。
[カテゴリ] ウィンドウで [Visual C++] ノードを展開し、[コード] をクリックします。
[テンプレート] ペイン で 、[ モジュール定義ファイル ] テンプレートを選択します。
[ 名前 ] ボックスに 「HelloWorld」と入力し、[ 場所 ] ボックスにファイルの既定のパスをそのまま使用します。
[追加] をクリックします。
次のコードを追加します。
LIBRARY HelloWorld EXPORTS RegisterModule
必要に応じて、/EXPORT:RegisterModule スイッチを使用して RegisterModule 関数をエクスポートできます。
[ プロジェクト ] メニューの [ HelloWorld のプロパティ] をクリックします。
ツリー ビューで [構成プロパティ ] ノードを展開し、[ リンカー ] ノードを展開して、[ コマンド ライン] をクリックします。
[ 構成 ] ドロップダウン ボックスで、[ すべての構成] を選択します。
[ 追加のオプション] ボックスに、「 /EXPORT:RegisterModule」と入力します。
[OK] をクリックします。
C++ ファイルを作成します。
ソリューション エクスプローラーで、[ソース ファイル] を右クリックし、[追加] をポイントして、[新しい項目] をクリックします。
[新しい項目の追加] ダイアログ ボックスが開きます。
[カテゴリ] ウィンドウで [Visual C++] ノードを展開し、[コード] をクリックします。
[テンプレート] ペイン で 、 C++ ファイル テンプレートを選択します。
[ 名前 ] ボックスに 「HelloWorld」と入力し、[ 場所 ] ボックスにファイルの既定のパスをそのまま使用します。
[追加] をクリックします。
次のコードを追加します。
#define _WINSOCKAPI_ #include <windows.h> #include <sal.h> #include <httpserv.h> // Create the module's global class. class MyGlobalModule : public CGlobalModule { public: // Process a GL_APPLICATION_START notification. GLOBAL_NOTIFICATION_STATUS OnGlobalPreBeginRequest( IN IPreBeginRequestProvider * pProvider ) { UNREFERENCED_PARAMETER( pProvider ); WriteEventViewerLog( "Hello World!" ); return GL_NOTIFICATION_CONTINUE; } VOID Terminate() { // Remove the class from memory. delete this; } MyGlobalModule() { // Open a handle to the Event Viewer. m_hEventLog = RegisterEventSource( NULL,"IISADMIN" ); } ~MyGlobalModule() { // Test whether the handle for the Event Viewer is open. if (NULL != m_hEventLog) { // Close the handle to the Event Viewer. DeregisterEventSource( m_hEventLog ); m_hEventLog = NULL; } } private: // Create a handle for the event viewer. HANDLE m_hEventLog; // Define a method that writes to the Event Viewer. BOOL WriteEventViewerLog(LPCSTR szNotification) { // Test whether the handle for the Event Viewer is open. if (NULL != m_hEventLog) { // Write any strings to the Event Viewer and return. return ReportEvent( m_hEventLog, EVENTLOG_INFORMATION_TYPE, 0, 0, NULL, 1, 0, &szNotification, NULL ); } return FALSE; } }; // Create the module's exported registration function. HRESULT __stdcall RegisterModule( DWORD dwServerVersion, IHttpModuleRegistrationInfo * pModuleInfo, IHttpServer * pGlobalInfo ) { UNREFERENCED_PARAMETER( dwServerVersion ); UNREFERENCED_PARAMETER( pGlobalInfo ); // Create an instance of the global module class. MyGlobalModule * pGlobalModule = new MyGlobalModule; // Test for an error. if (NULL == pGlobalModule) { return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY); } // Set the global notifications and exit. return pModuleInfo->SetGlobalNotifications( pGlobalModule, GL_PRE_BEGIN_REQUEST ); }
必要に応じて、呼び出し規約を使用してコードを
__stdcall (/Gz)
コンパイルできます。[ プロジェクト ] メニューの [ HelloWorld のプロパティ] をクリックします。
ツリー ビューで [ 構成プロパティ ] ノードを展開し、[ C/C++ ] ノードを展開して、[ 詳細設定] をクリックします。
[ 構成 ] ドロップダウン ボックスで、[ すべての構成] を選択します。
[ 呼び出し規約 ] ドロップダウン ボックスで、 __stdcall (/Gz) を選択します。
[OK] をクリックします。
モジュールのコンパイルとテスト
HTTP モジュールには、必要なものがすべて含まれています。 必要なのは、HTTP モジュールをコンパイルしてテストすることです。
プロジェクトをコンパイルしてテストするには
HTTP モジュールをコンパイルします。
[ビルド] メニューの [ソリューションのビルド] をクリックします。
Visual Studio でエラーや警告が返されなかったことを確認します。 エラーまたは警告が発生した場合は、プロジェクトをテストする前に、これらの問題を解決する必要があります。
HTTP モジュールの DLL ファイルを IIS フォルダーにコピーします。
Windows エクスプローラーを開き、C++ プロジェクトの作成時に指定された既定のフォルダーを見つけます。
ビルド オプションに応じて、プロジェクトの既定のフォルダーに Debug または Release という名前のフォルダーが表示されます。
[デバッグ] フォルダーまたは [リリース] フォルダー内で、HelloWorld.dll という名前のファイルを見つけます。
HelloWorld.dll ファイルを Inetsrv フォルダーにコピーします。既定では %WinDir%\System32\Inetsrv にあります。
HelloWorld.dll モジュールをモジュールの一覧に追加します (手順については、「 Native-Code HTTP モジュールの設計」を参照してください)。
インターネット エクスプローラーを使用して Web サイトを参照します。通常の Web サイト コンテンツが表示されます。
Windows イベント ビューアーを開き、グローバル アプリケーション ログに切り替えます。イベント ソースとして "IISADMIN" を一覧表示するエントリが表示されます。
イベントを右クリックし、[ プロパティ ] をクリックしてイベントの詳細を表示します。 [説明] ウィンドウに "Hello World!" というメッセージが表示されます。
設定のトラブルシューティング
モジュールがコンパイルされない場合、または期待どおりに動作しない場合は、次の領域をチェックできます。
エクスポートした関数に対して を指定
__stdcall
したか、呼び出し規則を使用してコンパイルを__stdcall (/Gz)
構成していることを確認します。定義ファイルに正しい
RegisterModule
エクスポートが追加されていることを確認します。定義ファイルがプロジェクト設定に追加されていることを確認します。 プロジェクト設定にファイルを追加するには、次の手順を実行します。
[プロジェクト] メニューの [プロパティ] をクリックします。
ツリー ビューで [ 構成プロパティ] ノードを展開し、[ リンカー ] ノードを展開して、[ 入力] をクリックします。
[ モジュール定義ファイル] 設定で、定義ファイルが一覧表示されていることを確認します。