接收 WMI 事件
WMI 包含事件基礎結構,其會產生 WMI 資料和服務變更的相關通知。 WMI 事件類別會在 發生特定事件時提供通知。
本主題將討論下列各節:
事件查詢
您可以建立 半非同步 或 非同步 查詢,以監視事件記錄檔、進程建立、服務狀態、電腦可用性或磁片磁碟機可用空間,以及其他實體或事件變更。 在腳本中, SWbemServices.ExecNotificationQuery 方法可用來訂閱事件。 在 C++中,會使用 IWbemServices::ExecNotificationQuery 。 如需詳細資訊,請參閱 呼叫方法。
標準 WMI 資料模型中變更的通知稱為 內部事件。 __InstanceCreationEvent 或 __NamespaceDeletionEvent 是內部事件的範例。 提供者為定義提供者事件所做的變更通知稱為 extrinsic 事件。 例如, 系統登錄提供者、 Power Management 事件提供者和 Win32 提供者 會定義自己的事件。 如需詳細資訊,請參閱 決定要接收的事件種類。
範例
下列腳本程式碼範例是事件類別的內建 __InstanceCreationEvent 查詢 Win32_NTLogEvent。 您可以在背景中執行此程式,並在發生事件時顯示訊息。 如果您關閉 [等候事件 ] 對話方塊,程式就會停止等候事件。 請注意,必須啟用 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 的 extrinsic 事件。 腳本會使用 對 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 事件提供者。 每個標準取用者類別都會透過傳送電子郵件訊息或執行腳本來回應具有不同動作的事件。 您不需要撰寫提供者程式碼,即可使用標準取用者類別來建立永久事件取用者。 如需詳細資訊,請參閱 使用標準取用者監視和回應事件。
提供事件
事件提供者是 COM 元件,可將事件傳送至 WMI。 您可以建立事件提供者,以在 C++ 或 C# 應用程式中傳送事件。 大部分的事件提供者都會管理 WMI 的物件,例如應用程式或硬體專案。 如需詳細資訊,請參閱 撰寫事件提供者。
計時或重複事件是在預先決定的時間發生的事件。
WMI 提供下列方式,為您的應用程式建立計時或重複事件:
- 標準 Microsoft 事件基礎結構。
- 特製化計時器類別。
如需詳細資訊,請參閱 接收計時或重複事件。 當您撰寫事件提供者時,請考慮 安全提供事件中所識別的安全性資訊。
建議將永久事件訂閱編譯為 \root\subscription 命名空間。 如需詳細資訊,請參閱 實作跨命名空間永久事件訂閱。
訂用帳戶配額
輪詢事件可能會降低支援大型資料集查詢之提供者的效能。 此外,具有動態提供者之命名空間讀取權限的任何使用者,都可以執行拒絕服務, (DoS) 攻擊。 WMI 會針對合併的所有使用者,以及位於 \root 命名空間之單一 __ArbitratorConfiguration 實例中的每個事件取用者,維護配額。 這些配額是全域的,而不是針對每個命名空間。 您無法變更配額。
WMI 目前會使用 __ArbitratorConfiguration的屬性強制執行配額。 每個配額都有每個使用者,以及包含所有使用者合併的總版本,而不是每個命名空間。 下表列出套用至 __ArbitratorConfiguration 屬性的配額。
Total/PerUser | Quota |
---|---|
TemporarySubscriptionsTotal TemporarySubscriptionsPerUser |
10,000 1,000 |
PermanentSubscriptionsTotal PermanentSubscriptionsPerUser |
10,000 1,000 |
PollingInstructionsTotal PollingInstructionsPerUser |
10,000 1,000 |
PollingMemoryTotal PollingMemoryPerUser |
10,000,000 個 (0x989680) 個位元組 5,000,000 個 (0x4CB40) 位元組 |
命名空間中 具有FULL_WRITE 許可權的系統管理員或使用者,可以修改 __ArbitratorConfiguration的單一實例。 WMI 會追蹤每個使用者的配額。