C++ を使用して非同期呼び出しを行う

C++ で記述された WMI アプリケーションは、IWbemServices COM インターフェイスの多くのメソッドを使用して非同期呼び出しを行うことができます。 ただし、"WMI メソッド" または "プロバイダー メソッド" を呼び出すための推奨される手順は、半同期呼び出しを使用することです。これは、半同期呼び出しは非同期呼び出しよりも安全だからです。 詳細については、「C++ を使用して半同期呼び出しを行う」および「非同期呼び出しでのセキュリティの設定」を参照してください。

次の手順では、プロセスのシンクを使用して非同期呼び出しを行う方法を説明します。

C++ を使用して非同期呼び出しを行うには

  1. IWbemObjectSink インターフェイスを実装します。

    非同期呼び出しを行うすべてのアプリケーションでは、IWbemObjectSink が実装されている必要があります。 一時イベント コンシューマーも、イベントの通知を受け取るために IWbemObjectSink を実装します。

  2. 対象の WMI 名前空間にログオンします。

    アプリケーションは、初期化フェーズ中、常に COM 関数 CoInitializeSecurity を呼び出す必要があります。 非同期呼び出しを行う前にそれが行われない場合、WMI は非同期呼び出しを完了せずにアプリケーション シンクを解放します。 詳細については、「WMI アプリケーションの COM の初期化」を参照してください。

  3. シンクのセキュリティを設定します。

    非同期呼び出しでは、WMI にアプリケーションへのアクセスを許可するなど、対応する必要があるさまざまなセキュリティの問題が発生します。 詳しくは、「非同期呼び出しでのセキュリティの設定」をご覧ください。

  4. 非同期呼び出しを行います。

    メソッドからは、WBEM_S_NO_ERROR 成功コードがすぐに返されます。 アプリケーションは、操作の完了を待機している間、他のタスクを続行できます。 WMI は、アプリケーションの IWbemObjectSink 実装でメソッドを呼び出して、アプリケーションに報告します。

  5. 必要に応じて、更新がないか実装を定期的にチェックします。

    アプリケーションは、WBEM_FLAG_SEND_STATUS への非同期呼び出しに lFlags パラメータを設定することで、中間状態の通知を受け取ることができます。 WMI は、IWbemObjectSinklFlags パラメータを WBEM_STATUS_PROGRESS に設定することで、呼び出しの状態を報告します。

  6. 必要に応じて、IWbemServices::CancelCallAsync メソッドを呼び出すことで、WMI が処理を完了する前に、呼び出しを取り消すことができます。

    CancelAsyncCall メソッドは、IWbemObjectSink インターフェイスへのポインターを直ちに解放することによって非同期処理を取り消し、CancelAsyncCall が返される前にポインターが解放されることを保証します。

    IWbemObjectSink をホストするために IUnsecured インターフェイスを実装するラッパー オブジェクトを使用している場合は、さらに複雑になる可能性があります。 アプリケーションは、元の非同期呼び出しで渡されたのと同じポインターを CancelAsyncCall に渡す必要があるため、取り消しが不要であることが明らかになるまで、アプリケーションはラッパー オブジェクトを保持する必要があります。 詳しくは、「非同期呼び出しでのセキュリティの設定」をご覧ください。

  7. 完了したら、ポインターをクリーンアップし、アプリケーションをシャットダウンします。

    WMI は SetStatus メソッドを介して最終的な状態呼び出しを提供します。

    注意

    最終的な状態の更新を送信した後、WMI は IWbemObjectSink インターフェイスを実装するクラスに対して Release メソッドを呼び出してオブジェクト シンクを解放します。 前の例では、これは QuerySink::Release メソッドです。 シンク オブジェクトの有効期間を制御する場合は、初期参照カウント 1 (1) でシンクを実装できます。

     

    クライアント アプリケーションが 2 つの異なる重複する非同期呼び出しで同じシンク インターフェイスを渡す場合、WMI ではコールバックの順序は保証されません。 重複する非同期呼び出しを行うクライアント アプリケーションは、異なるシンク オブジェクトを渡すか、呼び出しをシリアル化する必要があります。

次の例では、次の参照ステートメントと #include ステートメントが必要です。

#include <iostream>
using namespace std;
#pragma comment(lib, "wbemuuid.lib")
#include <wbemidl.h>

次の例では、ExecQueryAsync メソッドを使用して非同期クエリを作成する方法について説明しますが、セキュリティ設定の作成や IWbemObjectSink オブジェクトの解放は行いません。 詳しくは、「非同期呼び出しでのセキュリティの設定」をご覧ください。

// Set input parameters to ExecQueryAsync.
BSTR QueryLang = SysAllocString(L"WQL");
BSTR Query = SysAllocString(L"SELECT * FROM MyClass");

// Create IWbemObjectSink object and set pointer.
QuerySink *pSink = new QuerySink;

IWbemServices* pSvc = 0;

// Call ExecQueryAsync.
HRESULT hRes = pSvc->ExecQueryAsync(QueryLang, 
                                    Query, 
                                    0, 
                                    NULL, 
                                    pSink);

// Check for errors.
if (hRes)
{
    printf("ExecQueryAsync failed with = 0x%X\n", hRes);
    SysFreeString(QueryLang);
    SysFreeString(Query);
    delete pSink;    
    return ERROR;
}

Note

QuerySink クラスが定義されていないため、上記のコードはエラーなしでコンパイルされません。 QuerySink の詳細については、「IWbemObjectSink」を参照してください。

 

メソッドの呼び出し