使用 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. 如有必要,請定期檢查您的實作是否有更新。

    應用程式可以在非同步呼叫 中設定 lFlags 參數來接收中繼狀態的通知 ,以WBEM_FLAG_SEND_STATUS。 WMI 會藉由將IWbemObjectSinklFlags參數設定為WBEM_STATUS_PROGRESS來報告您的撥號狀態。

  6. 如有必要,您可以呼叫 IWbemServices::CancelCallAsync 方法,在 WMI 完成處理之前取消呼叫。

    CancelAsyncCall方法會立即釋放IWbemObjectSink介面的指標,並保證在 CancelAsyncCall傳回之前釋放指標,以取消非同步處理。

    如果您使用實作 IUnsecured 介面的包裝函式物件來裝載 IWbemObjectSink,您可能會發現一些額外的複雜性。 因為應用程式必須將相同的指標傳遞給在原始非同步呼叫中傳遞的 CancelAsyncCall ,所以應用程式必須保留包裝函式物件,直到它變得清楚不需要取消為止。 如需詳細資訊,請參閱 在非同步呼叫上設定安全性

  7. 完成後,清除指標並關閉應用程式。

    WMI 會透過 SetStatus 方法提供最終狀態呼叫。

    注意

    傳送最終狀態更新之後,WMI 會呼叫實作IWbemObjectSink介面之類別的Release方法,以釋放物件接收。 在上一個範例中,這是 QuerySink::Release 方法。 如果您想要控制接收物件的存留期,您可以使用一個 (1 個) 的初始參考計數來實作接收。

     

    如果用戶端應用程式在兩個不同的重迭非同步呼叫中傳遞相同的接收介面,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;
}

注意

上述程式碼在未發生錯誤的情況下編譯,因為尚未定義 QuerySink 類別。 如需 QuerySink的詳細資訊,請參閱 IWbemObjectSink

 

呼叫方法