CHttpModule::OnAsyncCompletion メソッド

非同期操作の処理が完了した後に発生する非同期完了イベントを処理するメソッドを表します。

構文

virtual REQUEST_NOTIFICATION_STATUS OnAsyncCompletion(  
   IN IHttpContext* pHttpContext,  
   IN DWORD dwNotification,  
   IN BOOL fPostNotification,  
   IN OUT IHttpEventProvider* pProvider,  
   IN IHttpCompletionInfo* pCompletionInfo  
);  

パラメーター

pHttpContext
[IN] IHttpContext インターフェイスへのポインター。

dwNotification
[IN] DWORD 関連する通知のビットマスクを含む値。

fPostNotification
[IN] true 通知が事後イベント用であることを示す場合は 。それ以外の場合は false

pProvider
[IN] IHttpEventProvider インターフェイスへのポインター。

pCompletionInfo
[IN] IHttpCompletionInfo インターフェイスへのポインター。

戻り値

REQUEST_NOTIFICATION_STATUS値。

解説

特定の通知に登録することによって呼び出される他の CHttpModule メソッドの多くと異なり、IIS は非同期操作が完了したときにのみモジュールの OnAsyncCompletion メソッドを呼び出します。 たとえば、要求レベルのモジュールが IHttpResponse::WriteEntityChunks メソッドを呼び出し、非同期完了を指定すると、IIS は操作が完了するとモジュールの OnAsyncCompletion メソッドを呼び出します。

IIS が メソッドを OnAsyncCompletion 呼び出すと、 パラメーターに通知の種類が dwNotification 指定され、 パラメーターを使用 fPostNotification して通知がイベントに対して行われたか、イベント後の通知であったかを示します。 IIS には、 IHttpCompletionInfo パラメーターによって pCompletionInfo 指されるインターフェイスも用意されています。 このインターフェイスを使用して、非同期完了に関する追加情報を取得できます。

次のコード例は、次のタスクを実行する HTTP モジュールを作成する方法を示しています。

  1. モジュールは、 RQ_BEGIN_REQUESTRQ_MAP_REQUEST_HANDLER 通知に登録します。

  2. モジュールは、CHttpModuleOnBeginRequestOnMapRequestHandler、およびOnAsyncCompletionメソッドを含むクラスを作成します。

  3. Web クライアントが URL を要求すると、IIS はモジュールの OnBeginRequest メソッドを呼び出します。 このメソッドは、次のタスクを実行します。

    1. 既存の応答バッファーをクリアし、応答の MIME の種類を設定します。

    2. 文字列の例を作成し、その文字列を Web クライアントに非同期的に返します。

    3. エラーまたは非同期完了をテストします。 非同期完了が保留中の場合、モジュールは保留中の通知状態を統合された要求処理パイプラインに返します。

  4. IIS はモジュール OnMapRequestHandler の メソッドを呼び出します。 このメソッドは、次のタスクを実行します。

    1. 現在の応答バッファーを Web クライアントにフラッシュします。

    2. エラーまたは非同期完了をテストします。 非同期完了が保留中の場合、モジュールは保留中の通知状態をパイプラインに返します。

  5. 非同期入力候補が必要な場合、IIS はモジュールの OnAsyncCompletion メソッドを呼び出します。 このメソッドは、次のタスクを実行します。

    1. 有効な IHttpCompletionInfo インターフェイスをテストします。 有効な IHttpCompletionInfo インターフェイスが渡された場合、メソッドは、それぞれ GetCompletionBytes メソッドと GetCompletionStatus メソッドを呼び出して、完了したバイトを取得し、非同期操作の状態を返します。

    2. 完了情報を含む文字列を作成し、その情報をイベントとしてイベント ビューアーのアプリケーション ログに書き込みます。

  6. モジュールは、 クラスを CHttpModule メモリから削除してから終了します。

#define _WINSOCKAPI_
#include <windows.h>
#include <sal.h>
#include <httpserv.h>
#include <wchar.h>

// Create the module class.
class MyHttpModule : public CHttpModule
{

public:

    REQUEST_NOTIFICATION_STATUS
    OnBeginRequest(
        IN IHttpContext * pHttpContext,
        IN IHttpEventProvider * pProvider
    )
    {
        UNREFERENCED_PARAMETER( pProvider );

        // Create an HRESULT to receive return values from methods.
        HRESULT hr;
        // Buffer to store the byte count.
        DWORD cbSent = 0;
        // Buffer to store if asyncronous completion is pending.
        BOOL fCompletionExpected = false;
        // Create an example string to return to the Web client.
        char szBuffer[] = "Hello World!";
        
        // Clear the existing response.
        pHttpContext->GetResponse()->Clear();
        // Set the MIME type to plain text.
        pHttpContext->GetResponse()->SetHeader(
            HttpHeaderContentType,"text/plain",
            (USHORT)strlen("text/plain"),TRUE);
        
        // Create a data chunk.
        HTTP_DATA_CHUNK dataChunk;
        // Set the chunk to a chunk in memory.
        dataChunk.DataChunkType = HttpDataChunkFromMemory;
        // Set the chunk to the buffer.
        dataChunk.FromMemory.pBuffer =
            (PVOID) szBuffer;
        // Set the chunk size to the buffer size.
        dataChunk.FromMemory.BufferLength =
            (USHORT) strlen(szBuffer);
        // Insert the data chunk into the response.
        hr = pHttpContext->GetResponse()->WriteEntityChunks(
            &dataChunk,1,TRUE,TRUE,&cbSent,&fCompletionExpected);

        // Test for a failure.
        if (FAILED(hr))
        {
            // Set the HTTP status.
            pHttpContext->GetResponse()->SetStatus(
                500,"Server Error",0,hr);
            // End additional processing.
            return RQ_NOTIFICATION_FINISH_REQUEST;
        }
        
        // Test for pending asynchronous operations.
        if (fCompletionExpected)
        {
            return RQ_NOTIFICATION_PENDING;
        }

        // Return processing to the pipeline.
        return RQ_NOTIFICATION_CONTINUE;
    }
    
    REQUEST_NOTIFICATION_STATUS
    OnMapRequestHandler(
        IN IHttpContext * pHttpContext,
        IN IMapHandlerProvider * pProvider
    )
    {
        // Create an HRESULT to receive return values from methods.
        HRESULT hr;
        // Buffer to store the byte count.
        DWORD cbSent = 0;
        // Buffer to store if asyncronous completion is pending.
        BOOL fCompletionExpected = false;

        // Flush the response to the client.
        hr = pHttpContext->GetResponse()->Flush(
            TRUE,FALSE,&cbSent,&fCompletionExpected);

        // Test for a failure.
        if (FAILED(hr))
        {
            // Set the HTTP status.
            pHttpContext->GetResponse()->SetStatus(
                500,"Server Error",0,hr);
        }

        // Test for pending asynchronous operations.
        if (fCompletionExpected)
        {
            return RQ_NOTIFICATION_PENDING;
        }

        // End additional processing.
        return RQ_NOTIFICATION_CONTINUE;
    }

    REQUEST_NOTIFICATION_STATUS
        OnAsyncCompletion(
        IN IHttpContext * pHttpContext,
        IN DWORD dwNotification,
        IN BOOL fPostNotification,
        IN IHttpEventProvider * pProvider,
        IN IHttpCompletionInfo * pCompletionInfo
        )
    {        
        if ( NULL != pCompletionInfo )
        {
            // Create strings for completion information.
            char szNotification[256] = "";
            char szBytes[256] = "";
            char szStatus[256] = "";

            // Retrieve and format the completion information.
            sprintf_s(szNotification,255,"Notification: %u",
                dwNotification);
            sprintf_s(szBytes,255,"Completion Bytes: %u",
                pCompletionInfo->GetCompletionBytes());
            sprintf_s(szStatus,255,"Completion Status: 0x%08x",
                pCompletionInfo->GetCompletionStatus());

            // Create an array of strings.
            LPCSTR szBuffer[3] = {szNotification,szBytes,szStatus};
            // Write the strings to the Event Viewer.
            WriteEventViewerLog(szBuffer,3);
        }
        
        // Return processing to the pipeline.
        return RQ_NOTIFICATION_CONTINUE;
    }

    MyHttpModule(void)
    {
        // Open a handle to the Event Viewer.
        m_hEventLog = RegisterEventSource( NULL,"IISADMIN" );
    }

    ~MyHttpModule(void)
    {
        // Test if 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:

    // Handle for the Event Viewer.
    HANDLE m_hEventLog;

    // Define a method that writes to the Event Viewer.
    BOOL WriteEventViewerLog(LPCSTR * lpStrings, WORD wNumStrings)
    {
        // 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, wNumStrings, 0, lpStrings, NULL );
        }
        return FALSE;
    }
};

// Create the module's class factory.
class MyHttpModuleFactory : public IHttpModuleFactory
{
public:
    HRESULT
    GetHttpModule(
        OUT CHttpModule ** ppModule, 
        IN IModuleAllocator * pAllocator
    )
    {
        UNREFERENCED_PARAMETER( pAllocator );

        // Create a new instance.
        MyHttpModule * pModule = new MyHttpModule;

        // Test for an error.
        if (!pModule)
        {
            // Return an error if we cannot create the instance.
            return HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY );
        }
        else
        {
            // Return a pointer to the module.
            *ppModule = pModule;
            pModule = NULL;
            // Return a success status.
            return S_OK;
        }            
    }

    void Terminate()
    {
        // Remove the class from memory.
        delete this;
    }
};

// Create the module's exported registration function.
HRESULT
__stdcall
RegisterModule(
    DWORD dwServerVersion,
    IHttpModuleRegistrationInfo * pModuleInfo,
    IHttpServer * pGlobalInfo
)
{
    UNREFERENCED_PARAMETER( dwServerVersion );
    UNREFERENCED_PARAMETER( pGlobalInfo );

    return pModuleInfo->SetRequestNotifications(
        new MyHttpModuleFactory,
        RQ_BEGIN_REQUEST | RQ_MAP_REQUEST_HANDLER,
        0
    );
}

モジュールは RegisterModule 関数をエクスポートする必要があります。 この関数をエクスポートするには、プロジェクトのモジュール定義 (.def) ファイルを作成するか、スイッチを使用してモジュールを /EXPORT:RegisterModule コンパイルします。 詳細については、「 チュートリアル: ネイティブ コードを使用したRequest-Level HTTP モジュールの作成」を参照してください。

必要に応じて、各関数の呼び出し規約を __stdcall (/Gz) 明示的に宣言するのではなく、呼び出し規約を使用してコードをコンパイルできます。

要件

Type 説明
Client - Windows Vista 上の IIS 7.0
- Windows 7 上の IIS 7.5
- Windows 8 の IIS 8.0
- Windows 10の IIS 10.0
サーバー - Windows Server 2008 の IIS 7.0
- Windows Server 2008 R2 上の IIS 7.5
- Windows Server 2012 上の IIS 8.0
- Windows Server 2012 R2 上の IIS 8.5
- Windows Server 2016上の IIS 10.0
製品 - IIS 7.0、IIS 7.5、IIS 8.0、IIS 8.5、IIS 10.0
- IIS Express 7.5、IIS Express 8.0、IIS Express 10.0
Header Httpserv.h

参照

CHttpModule クラス