使用 C++ 進行異步呼叫
以 C++ 撰寫的 WMI 應用程式可以使用 IWbemServices COM 介面的許多方法進行異步呼叫。 不過,建議呼叫 WMI 方法 或 提供者方法 時使用半同步呼叫,因為半同步呼叫比異步呼叫更安全。 如需詳細資訊,請參閱 使用 C++ 進行半同步呼叫,並在異步呼叫 上設定安全性。
下列程序描述如何在您的程序中使用接收器來進行異步呼叫。
使用 C++ 進行異步呼叫
實作 IWbemObjectSink 介面。
進行異步呼叫的所有應用程式都必須實作 IWbemObjectSink 。 暫存事件取用者也會實作 IWbemObjectSink 來接收事件的通知。
登入目標 WMI 命名空間。
應用程式在初始化階段一律必須呼叫 COM 函式 CoInitializeSecurity。 如果在進行異步呼叫之前未這麼做,WMI 會釋放應用程式接收器,並且不完成異步呼叫。 如需詳細資訊,請參閱 WMI 應用程式初始化 COM。
設定資料接收端的安全性。
異步呼叫會建立您可能必須處理的各種安全性問題,例如允許 WMI 存取您的應用程式。 如需詳細資訊,請參閱在異步呼叫上設定安全性 。
進行非同步呼叫。
方法會立即傳回 WBEM_S_NO_ERROR 成功代碼。 應用程式可以在等候作業完成時繼續執行其他工作。 WMI 會透過呼叫應用程式中 IWbemObjectSink 實作的方法來向應用程式回報。
如有必要,請定期檢查您的實作是否有更新。
應用程式可以在異步 WBEM_FLAG_SEND_STATUS呼叫 中設定 lFlags 參數,以接收中繼狀態的通知。 WMI 會藉由將 IWbemObjectSink 的 lFlags 參數設定為 WBEM_STATUS_PROGRESS,報告呼叫狀態。
如有必要,您可以呼叫 IWbemServices::CancelCallAsync 方法,在 WMI 完成處理之前取消呼叫。
CancelAsyncCall 方法藉由立即釋放指向 IWbemObjectSink介面的指標來取消異步處理,並保證在 CancelAsyncCall 返回之前釋放該指標。
如果您使用實作 IUnsecured 介面的包裝函式對象來裝載 IWbemObjectSink,您可能會發現一些額外的複雜問題。 由於應用程式必須將相同的指標傳遞給在原始異步呼叫中使用的 CancelAsyncCall,因此應用程式必須保留該包裝物件,直到確認不需要進行取消為止。 如需詳細資訊,請參閱在異步呼叫上設定安全性 。
完成後,清除指標並關閉應用程式。
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。
相關主題