使用标准使用者监视和响应事件

可以使用已安装的标准使用者类根据操作系统中的事件执行操作。 标准使用者是已注册的简单类,它们可定义永久使用者类。 每个标准使用者在收到事件通知后都会执行特定操作。 例如,可以定义 ActiveScriptEventConsumer 的实例,以便在计算机上的可用磁盘空间与指定大小不同时执行脚本。

WMI 将标准使用者编译为依赖于操作系统的默认命名空间,例如:

  • 在 Windows Server 2003 中,所有标准使用者默认编译为“Root\Subscription”命名空间。

注意

有关特定于每个 WMI 类的默认命名空间和操作系统,请参阅每个类主题的“备注和要求”部分。

 

下表列出并描述了 WMI 标准使用者。

标准使用者 说明
ActiveScriptEventConsumer 在收到事件通知时执行脚本。 有关详细信息,请参阅基于事件运行脚本
LogFileEventConsumer 在收到事件通知时,将自定义字符串写入文本日志文件。 有关详细信息,请参阅基于事件写入日志文件
NTEventLogEventConsumer 将特定消息记录到应用程序事件日志。 有关详细信息,请参阅日志记录到基于事件的 NT 事件日志
SMTPEventConsumer 每次向其传递事件时,使用 SMTP 发送电子邮件。 有关详细信息,请参阅基于事件发送电子邮件
CommandLineEventConsumer 在事件传递到本地系统时启动进程。 可执行文件必须位于安全位置,或者使用强访问控制列表 (ACL) 进行保护,以防止未经授权的用户将你的可执行文件替换为其他可执行文件。 有关详细信息,请参阅基于事件从命令行运行程序

 

以下过程介绍如何通过标准使用者监视和响应事件。 请注意,对于托管对象格式 (MOF) 文件、脚本或应用程序,该过程相同。

标准使用者监视和响应事件

  1. 使用 MOF 预处理器命令 #pragma namespace 指定 MOF 文件中的命名空间。 在脚本或应用程序中,在连接到 WMI 的代码中指定命名空间。

    以下 MOF 代码示例演示如何指定 root\subscription 命名空间。

    #pragma namespace ("\\\\.\\root\\subscription")
    

    大多数内部事件都与 root\cimv2 命名空间中的类实例的更改相关联。 但是,注册表事件(如 RegistryKeyChangeEvent)由系统注册表提供程序在 root\default 命名空间中触发。

    通过在事件的 __EventFilter 查询的 EventNamespace 属性中指定命名空间,使用者可以包括位于其他命名空间中的事件类。 内部事件类(如 __InstanceOperationEvent)在每个命名空间中都可用。

  2. 创建并填充标准使用者类的实例。

    此实例在 Name 属性中可能具有唯一值。 可以通过重用同一名称来更新现有使用者。

    InsertionStringTemplates 包含要在事件中插入的文本,该事件在 EventType 中指定。 可以使用文本字符串或直接引用属性。 有关详细信息,请参阅使用标准字符串模板用于事件查询的 SELECT 语句

    将现有源用于支持不带关联文本的插入字符串的事件日志。

    以下 MOF 代码示例演示如何使用 WSH 的现有源和 EventID 值 8。

    instance of NTEventLogEventConsumer as $Consumer
    {
        Name = "RunKeyEventlogConsumer";
        SourceName = "WSH";               
        EventID = 8;
        // Warning                              
        EventType = 2;
        // One string supplies the entire message          
        NumberOfInsertionStrings = 1;             
        // the %Hive% and %KeyPath% are properties of
        // the RegistryKeyChangeEvent instance 
        InsertionStringTemplates = 
            {"The key %Hive%\\%RootPath% has been modified."
            "Check if the change is intentional"};
    };
    
  3. 创建 __EventFilter 实例并定义事件查询。

    在以下示例中,筛选器监视注册启动程序的注册表项。 监视此注册表项可能很重要,因为未经授权的程序可以在该注册表项下注册自己,这会导致它在计算机启动时启动。

    instance of __EventFilter as $Filter
    {
    Name = "RunKeyFilter";
    QueryLanguage = "WQL"; 
    Query = "Select * from RegistryTreeChangeEvent"
        " where (Hive = \"HKEY_LOCAL_MACHINE\" and "
        "RootPath = \"Software\\\\Microsoft\\\\Windows"
        "\\\\CurrentVersion\\\\Run\")";
    
    // RegistryTreeChangeEvents only fire in root\default namespace
    EventNamespace = "root\\default";                       
    };
    
  4. 标识要监视的事件并创建事件查询。

    可以检查是否存在使用的内部事件或外部事件。 例如,使用注册表提供程序的 RegistryTreeChangeEvent 类监视对系统注册表的更改。

    如果不存在描述需要监视的事件的类,则必须创建自己的事件提供程序,并定义新的外部事件类。 有关详细信息,请参阅编写事件提供程序

    在 MOF 文件中,可以为筛选器和使用者定义别名,这提供了一种描述实例路径的简单方法。

    以下示例演示如何为筛选器和使用者定义别名

    instance of __EventFilter as $FILTER
    instance of LogFileEventConsumer as $CONSUMER
    
  5. 创建 __FilterToConsumerBinding 实例以关联筛选器和使用者类。 此实例确定,当发生与指定筛选器匹配的事件时,使用者指定的操作必须发生。 __EventFilter__EventConsumer 和 __FilterToConsumerBinding 必须在 CreatorSID 属性中具有相同的单独安全标识符 (SID)。 有关详细信息,请参阅将事件筛选器与逻辑使用者绑定

    以下示例演示如何通过对象路径标识实例,或使用别名作为对象路径的速记表达式。

    instance of __EventFilter as $FILTER
    instance of NTEventLogEventConsumer as $CONSUMER
    

    以下示例使用别名将筛选器绑定到使用者。

    instance of __FilterToConsumerBinding
    {
        Filter = $FILTER;
        Consumer = $CONSUMER;
    
    };
    

    可以将一个筛选器绑定到多个使用者,表明发生匹配事件时,必须执行多个操作;或者,可以将一个使用者绑定到多个筛选器,表明在发生与其中一个筛选器匹配的事件时必须执行该操作。

    根据使用者和事件的条件执行以下操作:

    • 如果其中一个永久使用者失败,请求事件的其他使用者会收到通知。
    • 如果删除事件,WMI 将触发 __EventDroppedEvent
    • 如果订阅此事件,它将返回已删除的事件,对 __EventConsumer 的引用表示失败的使用者。
    • 如果使用者失败,WMI 将触发 __ConsumerFailureEvent,其中可能包含 ErrorCode、ErrorDescription 和 ErrorObject 属性中的详细信息。

    有关详细信息,请参阅将事件筛选器与逻辑使用者绑定

示例

以下示例演示 NTEventLogEventConsumer 实例的 MOF。 编译此 MOF 后,尝试在注册表路径 HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run 中创建、删除或修改值的任何操作都会在源“WSH”下的应用程序事件日志中记录一个条目。

#pragma namespace ("\\\\.\\root\\subscription")
 
instance of __EventFilter as $Filter
{
    Name = "RunKeyFilter";
    QueryLanguage = "WQL";
    Query = "Select * from RegistryTreeChangeEvent"
            " where (Hive = \"HKEY_LOCAL_MACHINE\" and "
            "KeyPath = \"Software\\\\Microsoft\\\\Windows"
            "\\\\CurrentVersion\\\\Run\")";

    // RegistryTreeChangeEvents only fire
    // in root\default namespace
    EventNamespace = "root\\default";   
};
 
instance of NTEventLogEventConsumer as $Consumer
{
    Name = "RunKeyEventlogConsumer";
    SourceName = "WSH";               
    EventID = 8;
    EventType = 2;                            // Warning
    Category = 0;
    NumberOfInsertionStrings = 1;

    // the %Hive% and %KeyPath% are properties
    // of the RegistryKeyChangeEvent instance 
    InsertionStringTemplates = {"The key %Hive%\\%RootPath% "
        "has been modified. Check if the change is intentional"};
};
 

// Bind the filter to the consumer
instance of __FilterToConsumerBinding
{
    Filter = $Filter;
    Consumer = $Consumer;
};

安全接收事件