Получение уведомлений о асинхронных событиях

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

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

Инструментарий WMI использует свойства ловсрешолдоневентс и хигхсрешолдоневентс класса Win32 _ вмисеттинг , чтобы задать ограничения для предотвращения нехватки памяти. Минимальное значение указывает, когда инструментарий WMI должен запустить задолгое уведомление о событии, а максимальное значение указывает, когда следует запускать удаление событий. Значения по умолчанию для нижнего и верхнего пороговых значений — 1000000 (10 МБ) и 2000000 (20 МБ). Кроме того, можно задать свойство максваитоневентс , чтобы описать период времени, в течение которого WMI должен ожидать перед удалением событий. Значение по умолчанию для максваитоневентс — 2000, или 2 секунды.

Получение асинхронных уведомлений о событиях в VBScript

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

Получение асинхронных уведомлений о событиях в VBScript

  1. Создайте объект приемника, вызвав WScript. CreateObject и указав ProgID "вбемскриптинг" и тип объекта свбемсинк. Объект приемника получает уведомления.

  2. Напишите подпрограммы для каждого события, которое необходимо обменять. В следующей таблице перечислены события свбемсинк .

    Событие Значение
    онобжектреади Сообщает о возвратах объекта в приемник. Использование этого вызова возвращает один объект каждый раз, пока операция не будет завершена.
    OnCompleted Сообщает о завершении асинхронного вызова. Это событие никогда не происходит, если операция является неопределенной.
    онобжектпут Сообщает о завершении асинхронной операции размещения. Это событие возвращает путь к объекту экземпляра или сохраненного класса.
    OnProgress Сообщает состояние выполняемого асинхронного вызова. Не все поставщики поддерживают промежуточные отчеты о состоянии.
    Отменить Отменяет все необработанные асинхронные операции, связанные с этим приемником объектов.

Следующий пример кода VBScript уведомляет об удалении процессов с интервалом опроса 10 секунд. В этом скрипте онобжектреади ПРИЕМНИКа подпрограммы _ обрабатывает экземпляр события. В этом примере объект приемника называется "Sink", однако этот объект можно назвать по своему выбору.

strComputer = "." 
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\CIMV2") 
Set MySink = WScript.CreateObject( _
    "WbemScripting.SWbemSink","SINK_")

objWMIservice.ExecNotificationQueryAsync MySink, _
    "SELECT * FROM __InstanceDeletionEvent" _
    & " WITHIN 10 WHERE TargetInstance ISA 'Win32_Process'"


WScript.Echo "Waiting for events..."

While (True)
    Wscript.Sleep(1000)
Wend

Sub SINK_OnObjectReady(objObject, objAsyncContext)
    Wscript.Echo "__InstanceDeletionEvent event has occurred."
End Sub

Sub SINK_OnCompleted(objObject, objAsyncContext)
    WScript.Echo "Event call complete."
End Sub

Получение уведомлений о асинхронных событиях в C++

для выполнения асинхронного уведомления создается отдельный поток только для отслеживания и получения событий от инструментарий управления Windows (WMI) (WMI). Когда этот поток получает сообщение, поток уведомляет ваше основное приложение.

Нажимая отдельный поток, вы разрешаете основному процессу выполнять другие действия, ожидая прибытия события. Асинхронная доставка уведомлений повышает производительность, но может обеспечить меньшую безопасность, чем требуется. В C++ имеется возможность использовать интерфейс ивбемунсекуредапартмент или выполнять проверки доступа в дескрипторах безопасности. Дополнительные сведения см. в разделе Настройка безопасности при асинхронном вызове.

Настройка уведомлений о асинхронных событиях

  1. Перед инициализацией каких-либо асинхронных уведомлений убедитесь, что параметры предотвращения нехватки памяти правильно заданы в Win32 _ вмисеттинг.

  2. Определите тип событий, которые вы хотите получить.

    Инструментарий WMI поддерживает внутренние и внешние события. Внутреннее событие — это событие, предопределенное WMI, в то время как внешнее событие является событием, определенным сторонним поставщиком. Дополнительные сведения см. в разделе Определение типа получаемого события.

В следующей процедуре описывается получение асинхронных уведомлений о событиях в C++.

Получение асинхронных уведомлений о событиях в C++

  1. Настройте приложение с помощью вызовов функций CoInitializeEx и CoInitializeSecurity .

    Вызов CoInitializeEx инициализирует COM, а CoInitializeSecurity предоставляет WMI разрешение на вызов процесса потребителя. Функция CoInitializeEx также предоставляет возможность программировать многопоточное приложение, необходимое для асинхронного уведомления. Дополнительные сведения см. в разделе обслуживание безопасности WMI.

    Для правильной компиляции кода в этом разделе необходимы следующие ссылки и # операторы include.

    #define _WIN32_DCOM
    #include <iostream>
    using namespace std;
    #include <wbemidl.h>
    

    В следующем примере кода показано, как настроить временный потребитель событий с помощью вызовов CoInitializeEx и CoInitializeSecurity.

    void main(int argc, char **argv)
    {
        HRESULT hr = 0;
        hr = CoInitializeEx (0, COINIT_MULTITHREADED);
        hr = CoInitializeSecurity (NULL, 
           -1, 
           NULL, 
           NULL,   
           RPC_C_AUTHN_LEVEL_NONE, 
           RPC_C_IMP_LEVEL_IMPERSONATE, 
           NULL,
           EOAC_NONE,
           NULL); 
    
        if (FAILED(hr))
        {
           CoUninitialize();
           cout << "Failed to initialize security. Error code = 0x"
               << hex << hr << endl;
           return;
        }
    
    // ...
    }
    
  2. Создайте объект приемника с помощью интерфейса ивбемобжектсинк .

    Инструментарий WMI использует ивбемобжектсинк для отправки уведомлений о событиях и для сообщения о состоянии асинхронной операции или уведомления о событии.

  3. Зарегистрируйте потребителя событий с помощью вызова метода IWbemServices:: ExecNotificationQueryAsync .

    Убедитесь, что параметр преспонсехандлер указывает на объект приемника, созданный на предыдущем шаге.

    Назначение регистрации — получение только необходимых уведомлений. Получение избыточных уведомлений тратит время на обработку и доставку; и не использует возможности фильтрации WMI с максимальной вероятностью.

    Однако временный потребитель может получить более одного типа события. В этом случае временный потребитель должен выполнить отдельные вызовы IWbemServices:: ExecNotificationQueryAsync для каждого типа событий. Например, потребителю может требоваться уведомление при создании новых процессов (событие создания экземпляра или _ _ инстанцекреатионевент), а также об изменениях в некоторых разделах реестра (событие реестра, например регистрикэйчанжеевент). Таким образом, потребитель выполняет один вызов ExecNotificationQueryAsync для регистрации событий создания экземпляра и другой вызов ExecNotificationQueryAsync для регистрации событий реестра.

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

  4. Выполните все необходимые действия в потребителе события.

    Этот шаг должен содержать большую часть кода и включать такие действия, как отображение событий в пользовательский интерфейс.

  5. По завершении отмените регистрацию временного потребителя событий, вызвав событие IWbemServices:: канцеласинккалл .

    Независимо от того, завершился ли вызов канцеласинккалл успешно или нет, не удаляйте объект приемника до тех пор, пока значение счетчика ссылок на объект не достигнет нуля. Дополнительные сведения см. в разделе вызов метода.