接收 WMI 事件

WMI 包含一个事件基础结构,用于生成有关 WMI 数据和服务更改的通知。 WMI 事件类 在发生特定事件时提供通知。

本主题将讨论以下部分:

事件查询

可以创建 半异步异步 查询来监视对事件日志、进程创建、服务状态、计算机可用性或磁盘驱动器可用空间和其他实体或事件的更改。 在脚本中, SWbemServices.ExecNotificationQuery 方法用于订阅事件。 在 C++中,使用 IWbemServices::ExecNotificationQuery 。 有关详细信息,请参阅 调用方法

标准 WMI 数据模型中更改的通知称为 内部事件__InstanceCreationEvent__NamespaceDeletionEvent 是内部事件的示例。 提供程序为定义提供程序事件而做出的更改通知称为 外在事件。 例如, 系统注册表提供程序电源管理事件提供程序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 属性的配额。

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 跟踪每用户配额。

使用 WMI