共用方式為


接收非同步事件通知

異步事件通知是一種技術,可讓應用程式在不壟斷系統資源的情況下持續監視事件。 異步事件通知與其他異步呼叫具有相同的安全性限制。 您可以改為進行半同步呼叫。 如需詳細資訊,請參閱 呼叫 方法

路由傳送至客戶端的異步事件佇列有可能成長得異常龐大。 因此,WMI 會實作全系統原則,以避免記憶體不足。 WMI 會減少事件的發生速度,或在佇列成長超過特定大小時,開始丟棄事件。

WMI 會使用 LowThresholdOnEventsHighThresholdOnEvents Win32_WMISetting 類別 属性來設定記憶體不足避免的限制。 最小值表示 WMI 何時應開始減慢事件通知速度,而最大值則表示何時開始捨棄事件。 低臨界值的預設值為100000000(10 MB)和2000000000(20 MB)。 此外,您可以設定 MaxWaitOnEvents 屬性,以指定 WMI 卸除事件前應等候的時間量。 MaxWaitOnEvents 的預設值為 2000 或 2 秒。

在 VBScript 中接收異步事件通知

接收事件通知的腳本呼叫基本上與具有相同安全性問題的所有異步呼叫相同。 如需詳細資訊,請參閱使用 VBScript 進行異步呼叫

在 VBScript 中接收異步事件通知

  1. 要建立一個接收物件,請呼叫 WScript.CreateObject,並指定progID為“WbemScripting”及物件類型為SWbemSink 。 接收端物件會收到通知。

  2. 針對您想要處理的每個事件撰寫子程式。 下表列出 SWbemSink 事件。

    事件 意義
    OnObjectReady 向接收方回報物件的返回。 每次使用這個呼叫時,都會傳回一個 物件,直到作業完成為止。
    OnCompleted 報告異步呼叫完成的時間。 如果作業無限期,則永遠不會發生此事件。
    OnObjectPut 通知異步寫入操作的完成。 這個事件會傳回實例或已儲存類別的物件路徑。
    進度中 報告進行中的異步呼叫狀態。 並非所有提供者都支援過渡進度報告。
    取消 取消所有與此對象接收器相關聯的未完成異步操作。

     

下列 VBScript 程式代碼範例會以 10 秒輪詢間隔通知刪除進程。 在此腳本中,子程式SINK_OnObjectReady會處理事件發生。 在這個範例中,接收物件的名稱為「Sink」,不過您可以隨意為此物件命名。

strComputer = "." 
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\CIMV2") 
Set MySink = WScript.CreateObject( _
    "WbemScripting.SWbemSink","SINK_")

objWMIservice.ExecNotificationQueryAsync MySink, _
    "SELECT * FROM __InstanceDeletionEvent" _
    & " WITHIN 10 WHERE TargetInstance ISA 'Win32_Process'"


WScript.Echo "Waiting for events..."

While (True)
    Wscript.Sleep(1000)
Wend

Sub SINK_OnObjectReady(objObject, objAsyncContext)
    Wscript.Echo "__InstanceDeletionEvent event has occurred."
End Sub

Sub SINK_OnCompleted(objObject, objAsyncContext)
    WScript.Echo "Event call complete."
End Sub

在 C++ 中接收異步事件通知

若要執行異步通知,您只建立個別線程來監視和接收來自 Windows Management Instrumentation (WMI) 的事件。 當該線程收到訊息時,線程會通知您的主要應用程式。

藉由指定個別線程,您可以允許主要進程在等候事件到達時執行其他活動。 異步傳遞通知可改善效能,但可提供比您想要的安全性少。 在 C++ 中,您可以選擇使用 IWbemUnsecuredApartment 介面,或對安全性描述項執行存取檢查。 如需詳細資訊,請參閱在異步呼叫上設定安全性

設定異步事件通知

  1. 初始化任何異步通知之前,請確定您已在 Win32_WMISetting中正確設定記憶體不足避免參數。

  2. 判斷您想要接收的事件種類。

    WMI 支援內在和外在事件。 內部事件是由 WMI 預先定義的事件,而外部事件是由第三方提供者所定義的事件。 如需詳細資訊,請參閱 判斷要接收的事件類型

下列程式描述如何在 C++ 中接收異步事件通知。

若要在 C++ 中接收異步事件通知

  1. 使用對 CoInitializeExCoInitializeSecurity 函式的呼叫來設定您的應用程式。

    呼叫 CoInitializeEx 會初始化 COM,而 CoInitializeSecurity 則授予 WMI 許可權以呼叫消費者的進程。 CoInitializeEx 函式也會讓您能夠設計多線程應用程式,這是異步通知的必要專案。 如需詳細資訊,請參閱 維護 WMI 安全性

    本主題中的程式代碼需要下列參考和 #include 語句才能正確編譯。

    #define _WIN32_DCOM
    #include <iostream>
    using namespace std;
    #include <wbemidl.h>
    

    下列程式代碼範例說明如何透過呼叫 CoInitializeEx 和 CoInitializeSecurity 來設定暫時事件使用者。

    void main(int argc, char **argv)
    {
        HRESULT hr = 0;
        hr = CoInitializeEx (0, COINIT_MULTITHREADED);
        hr = CoInitializeSecurity (NULL, 
           -1, 
           NULL, 
           NULL,   
           RPC_C_AUTHN_LEVEL_NONE, 
           RPC_C_IMP_LEVEL_IMPERSONATE, 
           NULL,
           EOAC_NONE,
           NULL); 
    
        if (FAILED(hr))
        {
           CoUninitialize();
           cout << "Failed to initialize security. Error code = 0x"
               << hex << hr << endl;
           return;
        }
    
    // ...
    }
    
  2. 建立接收物件透過 IWbemObjectSink 介面。

    WMI 使用 IWbemObjectSink 傳送事件通知,以及報告異步操作或事件通知的狀態。

  3. 透過呼叫 IWbemServices::ExecNotificationQueryAsync 方法以註冊您的事件使用者。

    請確定 pResponseHandler 參數指向在上一個步驟中建立的接收物件。

    註冊的目的是只接收必要的通知。 接收多餘的通知會浪費處理和傳遞時間:和不會使用 WMI 的篩選功能來發揮最大潛力。

    不過,暫時使用者可以接收多種事件類型。 在此情況下,暫時取用者必須針對每個事件類型分別呼叫 IWbemServices::ExecNotificationQueryAsync。 例如,取用者可能需要在建立新進程時通知(實例建立事件或 __InstanceCreationEvent),以及特定登錄機碼的變更(例如 RegistryKeyChangeEvent的登錄事件)。 因此,消費者會呼叫 ExecNotificationQueryAsync 來註冊實例創建事件,並使用另一個呼叫 ExecNotificationQueryAsync 來註冊登錄事件。

    如果您選擇建立註冊多個事件的事件消費者,您應該避免向相同的接收器註冊多個類別。 相反地,應對每個已註冊事件類別使用單獨的接收器。 擁有專用的水槽可以簡化處理並協助維護,讓您在取消一個註冊時不會影響其他註冊。

  4. 在您的事件消費者中執行任何必要的活動。

    此步驟應該包含大部分的程序代碼,並包含這類活動,例如將事件顯示給使用者介面。

  5. 完成後,請取消註冊暫存事件取用者,並呼叫 IWbemServices::CancelAsyncCall 事件。

    無論呼叫 CancelAsyncCall 成功或失敗,在對象參考計數達到零之前,請勿刪除接收物件。 如需詳細資訊,請參閱 呼叫 方法