接收 WMI 事件
WMI 包含事件基礎結構,可產生 WMI 數據和服務變更的相關通知。 WMI 事件類別 在特定事件發生時提供通知。
本主題將討論下列各節:
事件查詢
您可以建立 半異步 或 異步 查詢,以監視事件記錄、進程建立、服務狀態、計算機可用性或磁碟驅動器可用空間及其他實體或事件變更。 在腳本中,SWbemServices.ExecNotificationQuery 方法會用來訂閱事件。 在 C++ 中,會使用 IWbemServices::ExecNotificationQuery。 如需詳細資訊,請參閱 呼叫 方法。
標準 WMI 資料模型中變更的通知稱為 內部事件。 __InstanceCreationEvent 或 __NamespaceDeletionEvent 是內部事件的範例。 提供者為定義提供者事件所做的變更通知稱為 外部事件。 例如,System Registry Provider、Power Management 事件提供者,以及 Win32 提供者 定義自己的事件。 如需詳細資訊,請參閱 判斷要接收的事件類型。
例
下列腳本程式代碼範例是一個對事件類別 Win32_NTLogEvent的內建 __InstanceCreationEvent 查詢。 您可以在背景執行此程式,並在有事件時顯示訊息。 如果您關閉 等候事件 對話框,程式就會停止等候事件。 請注意,必須啟用 SeSecurityPrivilege。
Sub SINK_OnObjectReady(objObject, objAsyncContext)
WScript.Echo (objObject.TargetInstance.Message)
End Sub
Set objWMIServices = GetObject( _
"WinMgmts:{impersonationLevel=impersonate, (security)}")
' Create the event sink object that receives the events
Set sink = WScript.CreateObject("WbemScripting.SWbemSink","SINK_")
' Set up the event selection. SINK_OnObjectReady is called when
' a Win32_NTLogEvent event occurs
objWMIServices.ExecNotificationQueryAsync sink,"SELECT * FROM __InstanceCreationEvent " & "WHERE TargetInstance ISA 'Win32_NTLogEvent' "
WScript.Echo "Waiting for events"
# Define event Query
$query = "SELECT * FROM __InstanceCreationEvent
WHERE TargetInstance ISA 'Win32_NTLogEvent' "
<# Register for event - also specify an action that
displays the log event when the event fires.#>
Register-WmiEvent -Source Demo1 -Query $query -Action {
Write-Host "Log Event occured"
$global:myevent = $event
Write-Host "EVENT MESSAGE"
Write-Host $event.SourceEventArgs.NewEvent.TargetInstance.Message}
<# So wait #>
"Waiting for events"
下列 VBScript 程式代碼範例顯示登錄提供者所定義之外部事件 __RegistryValueChangeEvent。 腳本會使用呼叫 SWbemServices.ExecNotificationQueryAsync來建立暫存取用者,而且只有在腳本執行時才會收到事件。 下列腳本會無限期執行,直到計算機重新啟動、WMI 停止或腳本停止為止。 若要手動停止文稿,請使用任務管理器來停止進程。 若要以程式設計方式停止它,請使用 Win32_Process 類別中的 Terminate 方法。 如需詳細資訊,請參閱在異步呼叫上設定安全性 。
strComputer = "."
Set objWMIServices=GetObject( _
"winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\default")
set objSink = WScript.CreateObject("WbemScripting.SWbemSink","SINK_")
objWMIServices.ExecNotificationQueryAsync objSink, _
"Select * from RegistryValueChangeEvent Where Hive = 'HKEY_LOCAL_MACHINE' and KeyPath = 'SYSTEM\\ControlSet001\\Control' and ValueName = 'CurrentUser'"
WScript.Echo "Waiting for events..."
While (True)
WScript.Sleep (1000)
Wend
WScript.Echo "Listening for Registry Change Events..." & vbCrLf
While(True)
WScript.Sleep 1000
Wend
Sub SINK_OnObjectReady(wmiObject, wmiAsyncContext)
WScript.Echo "Received Registry Value Change Event" & vbCrLf & wmiObject.GetObjectText_()
End Sub
事件消費者
您可以在腳本或應用程式執行時,使用下列消費端來監視或取用事件:
臨時事件消費者
暫時使用者 是一個接收 WMI 事件的 WMI 用戶端應用程式。 WMI 包含唯一介面,用來指定要傳送至用戶端應用程式的 WMI 事件。 暫時事件取用者被稱為暫時性是因為它只有在用戶特別載入時才會運作。 如需詳細資訊,請參閱「應用程式運行期間接收事件」。
永久事件消費者
永久性消費者 是能夠隨時接收 WMI 事件的 COM 物件。 永久事件取用者使用一組持久性物件和篩選器來擷取 WMI 事件。 如同暫時性事件使用者,您可以設定一系列的 WMI 物件和篩選器,以擷取 WMI 事件。 當發生符合篩選的事件時,WMI 會載入永久事件消費者,並通知其事件內容。 由於永久取用者是在 WMI 存放庫中實作,且是一個在 WMI 中註冊的可執行檔,永久事件取用者在建立後即可運行並接收事件,即使在作業系統重新啟動後,只要 WMI 持續運行,依然會接收事件。 如需詳細資訊,請參閱 隨時接收事件。
接收事件的腳本或應用程式有特殊的安全性考慮。 如需詳細資訊,請參閱 保護 WMI 事件。
應用程式或文稿可以使用內建 WMI 事件提供者,提供 標準取用者類別。 每個標準取用者類別都會傳送電子郵件訊息或執行腳本,以回應具有不同動作的事件。 您不需要撰寫提供者程序代碼,即可使用標準取用者類別來建立永久事件取用者。 如需更多資訊,請參閱 使用標準消費者監控和回應事件。
提供事件
事件提供者是將事件傳送至 WMI 的 COM 元件。 您可以建立事件提供者,以在C++或 C# 應用程式中傳送事件。 大部分的事件提供者都會管理 WMI 的物件,例如應用程式或硬體專案。 如需詳細資訊,請參閱 撰寫事件提供者。
計時或重複事件是在預先決定時間發生的事件。
WMI 提供下列方式,為您的應用程式建立計時或重複事件:
- 標準Microsoft事件基礎結構。
- 特殊化定時器類別。
如需更多資訊,請參閱 接收定時或重複事件。 當您撰寫事件提供者時,請考慮 安全地提供事件中所識別的安全資訊。
建議將永久事件訂閱編譯成 \root\subscription 命名空間。 如需詳細資訊,請參閱 實作跨命名空間永久事件訂閱。
訂閱配額
輪詢操作可能會降低支援龐大數據集查詢的提供者的效能。 此外,具有動態提供者之命名空間讀取許可權的任何使用者,都可以執行阻斷服務 (DoS) 攻擊。 WMI 會在位於 \root 命名空間的單一 __ArbitratorConfiguration 實例中,維持所有使用者的總配額,以及每個事件取用者的配額。 這些配額是全域的,而不是針對每個命名空間。 您無法變更配額。
WMI 目前會使用 __ArbitratorConfiguration的屬性來強制執行配額。 每個配額都有一個針對每位使用者的版本,以及一個合計所有使用者的總版本,而不是針對每個命名空間。 下表列出套用至 __ArbitratorConfiguration 屬性的配額。
總計/每位使用者 | 配額 |
---|---|
暫時訂閱總數 每位用戶的臨時訂閱數 |
一萬 1,000 |
永久訂閱總數 每位用戶的永久訂閱 |
一萬 1,000 |
投票說明總數 用戶投票說明 |
10,000 1,000 |
輪詢記憶體總數 PollingMemoryPerUser |
10,000,000 0x989680 個字節 5,000,000 位元組(0x4CB40) |
命名空間中具有 FULL_WRITE 許可權的系統管理員或使用者,可以修改 __ArbitratorConfiguration的單一實例。 WMI 會追蹤每個使用者配額。