このチュートリアルでは、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++] ノードを展開し、[コード] をクリックします。
[テンプレート] ウィンドウ で 、 Module-Definition ファイル テンプレートを 選択します。
[ 名前 ] ボックスに 「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 という名前のフォルダーが表示されます。
Debug フォルダーまたは Release フォルダー内で、HelloWorld.dllという名前のファイルを見つけます。
HelloWorld.dll ファイルを Inetsrv フォルダーにコピーします。このフォルダーは、既定で \System32\Inetsrv %WinDir%にあります。
HelloWorld.dll モジュールをモジュールの一覧に追加します (手順については、「 Native-Code HTTP モジュールの設計」を参照してください)。
Internet Explorer を使用して Web サイトを参照します。通常の Web サイトのコンテンツが表示されます。
Windows イベント ビューアーを開き、グローバル アプリケーション ログに切り替えます。"IISADMIN" をイベント ソースとして一覧表示するエントリが表示されます。
イベントを右クリックし、[ プロパティ ] をクリックしてイベントの詳細を表示します。 [説明] ウィンドウに "Hello World!" というメッセージが表示されます。
設定のトラブルシューティング
モジュールがコンパイルされない場合、または期待どおりに動作しない場合は、確認できるいくつかの領域を次に示します。
エクスポートした関数の
__stdcallを指定していること、または__stdcall (/Gz)呼び出し規則を使用してコンパイルを構成していることを確認します。正しい
RegisterModuleエクスポートが定義ファイルに追加されていることを確認します。プロジェクト設定に定義ファイルが追加されていることを確認します。 プロジェクト設定にファイルを追加するには、次の手順を実行します。
プロジェクト メニューで、プロパティをクリックします。
ツリー ビューで [構成プロパティ] ノードを展開し、[ リンカー ] ノードを展開して、[ 入力] をクリックします。
モジュール定義ファイルの設定では、定義ファイルが一覧表示されていることを確認します。