События Windows Management Instrumentation (WMI)

События Windows Management Instrumentation (WMI) WMI - администрирование Windows

События WMI (Windows Management Instrumentation) являются, пожалуй самым мощным средством администрирования Windows. В простом варианте, события WMI – это подписка на извещения об любых изменения в состоянии логического или физического ком­понента информационной системы, доступ к которому может быть получен с помощью Windows Management Instrumentation.

Например:

  • Запуск заданного процесса или службы (или все вместе)
  • Появление в журнале событий Windows заданного сообщения
  • Изменения в файловой системе – объем диска, появление нового файла и так далее
  • Изменения заданного ключа реестра

При работе с WMI событиями происходит взаимодействие между провайдерами (event providers), роль которых формировать извещение и зарегистрированными подписчиками на эти изве­щения — потребителями (event consumers).

Все события WMI можно разделить на три категории: внутренние, внешние и события таймера. Каждой категории в репозитории CIM соответствует определен­ный класс-потомок абстрактного класса __Event. Так, внешние обрабатываются с помощью класса __ExtrinsicEvent, внутренним соответствуют три разных класса — __NamespaceOperationEvent, __ClassOperationEvent и __InstanceOperationEvent, событиям таймера  — класс __TimerEvent.

Также, WMI события можно разделить на временные и постоянные.

Как только возникает событие, WMI автоматически создает экземп­ляр того класса, которому оно соответствует. Давайте рассмотрим каждый тип событий WMI по отдельности.

Внутренние события WMI

Данный тип предоставляет возможность контролировать изменения в состоянии тех управляемых ресурсов, которые обрабатываются отдельным классом WMI и хранятся в CIM, плюс, изменения в структуре самого репозитория CIM. Пользователь может получить извещения о создании, изменении и удалении экземпляров заданного классов, а также самих классов и пространств имен.

Как уже было сказано, внутренним соответствуют три разных класса:

__ InstanceOperationEvent — является базовым для всех внутренних событий WMI, которые относятся к экземпляру. Например:

  • Был создан новый экземпляр заданного класса
    (подкласс __InstanceCreationEvent)
  • Модификация существующего экземпляра класса
    (подкласс __InstanceModificationEvent);
  • Удаление экземпляра класса
    (подкласс __InstanceDeletionEvent).

__NamespaceOperationEvent — является базовым для всех внутренних событий WMI, которые относятся к пространству имен.

  • Создание нового пространства имен

    (подкласс __NamespaceCreationEvent)

  • Модификация существующего пространства имен
    (подкласс __NamespaceModificationEvent);
  • Удаление пространства имен
    (подкласс __NamespaceDeletionEvent).

__ClassOperationEvent — является базовым для всех внутренних событий WMI, которые относятся к классу.

  • Создание нового класса
    (подкласс __ClassCreationEvent)
  • Модификация существующего класса
    (подкласс __ClassModificationEvent);
  • Удаление класса
    (подкласс __ClassDeletionEvent).

Что бы произвести подписку на извещения, нужно выполнить WQL запрос. Что бы выполнить WQL запрос для получения извещения, используется метод ExecNotificationQuery объекта SWbemServices. Давайте рассмотрим три примера, каждый будет обрабатывать экземпляр блокнота (notepad.exe) – класс __ InstanceOperationEvent:

'*********************************************
' Имя: notepad_creation.vbs
' Ожидание на запуск процесса notepad.exe
'*********************************************
Option Explicit
Dim objService, objEventSource, objEvent, strResult
Set objService = GetObject("WinMgmts:\\.\Root\CIMV2")
Set objEventSource = objService.ExecNotificationQuery ("SELECT * FROM __InstanceCreationEvent " & _
             "WITHIN 2 WHERE TargetInstance ISA 'Win32_Process' AND TargetInstance.Name='notepad.exe'")          
'Ждем наступления события WMI и записываем в переменную objEvent
Set objEvent = objEventSource.NextEvent
WScript.Echo "Запущен блокнот"

Тут все просто, как только произойдет запуск в системе процесса notepad.exe, нам будет выдано сообщение об этом.

'*********************************************
' Имя: notepad_creation.vbs
' Ожидание на запуск процесса notepad.exe
'*********************************************
Option Explicit
Dim objService, objEventSource, objEvent, strResult
Set objService = GetObject("WinMgmts:\\.\Root\CIMV2")
Set objEventSource = objService.ExecNotificationQuery ("SELECT * FROM __InstanceCreationEvent " & _
             "WITHIN 2 WHERE TargetInstance ISA 'Win32_Process' AND TargetInstance.Name='notepad.exe'")          
'Ждем наступления события WMI и записываем в переменную objEvent
Set objEvent = objEventSource.NextEvent
WScript.Echo "Запущен блокнот"

В данном примере, как только будет закрыт процесс notepad.exe, мы получим извещание.

'*********************************************
' Имя: notepad_modification.vbs
' Ожидание на изменения в процессе notepad.exe
' Для проверки, просто запустите блокнот и введите в него какой то тект
'*********************************************
Option Explicit
Dim objService, objEventSource, objEvent, strResult
Set objService = GetObject("WinMgmts:\\.\Root\CIMV2")
Set objEventSource = objService.ExecNotificationQuery ("SELECT * FROM __InstanceModificationEvent " & _
             "WITHIN 2 WHERE TargetInstance ISA 'Win32_Process' AND TargetInstance.Name='notepad.exe'")          
'Ждем наступления события WMI и записываем в переменную objEvent
Set objEvent = objEventSource.NextEvent
WScript.Echo "Были изменеиря в блокноте"

Ну и тут, происходит слежение за изменениями в экземпляре (блокнот). Если вы запустите сценарий, а потом Блокнот, то как только, вы переместите программу, или измените ее размер, или просто введете текст, будет выдано сообщение.

Внешние события WMI

Если нужно проконтролировать изменения объекта, для которого в CIM не предусмотрено отдельного класса, то применяются внешние события. Примером является изменение значения определенного ключа в реестре. Что бы создать внешнюю подписку, надо, чтобы она поддерживалось соответствующим провайдером WMI. Как уже упоминалось выше, для обработки внешних событий WMI используется класс __ExtrinsicEvent, сам провайдер должен иметь в своем составе класс, который является потомком  __ExtrinsicEvent, который будет описывать событие.

В случае реестра, в пространстве имен Rootdefault у класса __ExtrinsicEvent есть дочерний класс RegistryEvent, который содержит дочерний объект RegistryKeyChangeEvent, который и оповещает потребителей событий об из­менениях, которые происходят с ключом реестра. Тут для выполнение WQL-запроса используется метод Exec­NotificationQueryAsync класса swbemservices. Так, для того чтобы проследить за изме­нениями ключа Software\Microsoft\Windows Script Host\TrustPolicy, с помо­щью которого задается политика безопасности при работе с Windows Script Host, используется такой WQL-запрос:

«SELECT * FROM RegistryKeyChangeEvent WHERE Hive=’HKEY_LOCAL_MACHINE’ AND KeyPath=’Software\Microsoft\Windows Script Host\TrustPolicy’

События таймера

В отличие от внутренних и внешних, WMI события таймера, кото­рые могут происходить либо один раз в определенное время, либо несколь­ко раз через заданные интервалы времени, настраиваются самим потребите­лем. Извещения о событиях таймера могут быть получены в любом пространстве имен. Более детально данный тип я разберу в отдельной статье.

Временные потребители

Временные события WMI позволяют получить извещение только один раз, примеры выше с работой процесса notepad.exe. Как только событие происходит, скрипт завершает свою работу. Хотя тут есть один нюанс:

'*********************************************
' Имя: process_creation.vbs
' Ожидание на запуск процесса
'*********************************************
Option Explicit
Dim objService, objEventSource, objEvent, strResult
Set objService = GetObject("WinMgmts:\\.\Root\CIMV2")
Set objEventSource = objService.ExecNotificationQuery ("SELECT * FROM __InstanceCreationEvent " & _
             "WITHIN 2 WHERE TargetInstance ISA 'Win32_Process'")    
'Вечный цикл                           
do while TRUE
     Set objEvent = objEventSource.NextEvent
     WScript.Echo "Запущен " & objEvent.TargetInstance.Name
Loop

В данном случае используется цикл do while…Loop, условие выхода задано так, что в теле цикла будет постоянно происходить подписка на событие WMI. И, если, через диспетчер задач принудительно не завершить процесс wscript.exe, то каждый раз при запуске нового процесса будет выводиться сообщение. Не забываем, что для внутреннего используется метод ExecNotificationQuery, а для внешних – ExecNotificationQueryAsync. Метод NextEvent объекта swbemEventsource пере­водится в режим ожидания наступления события, в нашем случае бесконечно. При регистрации внешних событий WMI дополнительно используется объект swbemsink.

Скачать архив с примерами

Постоянные потребители

Постоянные потребители WMI событий регистрируются в самом репозитории CIM. При этом, активности скрипта не требуется, то есть, даже после перезагрузки системы будет происходить слежка за объектом, до тех пор, пока со­бытие не будет удалено из CIM явным образом.

Оцените статью
Технологии программирования и ведение блога
Добавить комментарий