Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Асинхронное уведомление о событиях — это метод, позволяющий приложению постоянно отслеживать события без монополизации системных ресурсов. Асинхронные уведомления о событиях имеют те же ограничения безопасности, что и другие асинхронные вызовы. Вместо этого можно выполнять полусинхронные вызовы. Дополнительные сведения см. в статье Вызов метода.
Очередь асинхронных событий, маршрутизированных на клиента, может увеличиться исключительно большой. Поэтому WMI реализует системную политику, чтобы избежать нехватки памяти. WMI либо замедляет события, либо начинает удалять события из очереди, когда очередь растет мимо определенного размера.
WMI использует свойства LowThresholdOnEvents и HighThresholdOnEvents класса Win32_WMISetting, чтобы задать ограничения на предотвращение нехватки памяти. Минимальное значение указывает, когда WMI должен начать замедлять уведомления о событиях, а максимальное значение указывает, когда следует начать игнорировать события. Значения по умолчанию для низких и высоких пороговых значений : 1000000 (10 МБ) и 2000000 (20 МБ). Кроме того, можно задать свойство MaxWaitOnEvents, чтобы описать время ожидания WMI перед удалением событий. Значение по умолчанию для MaxWaitOnEvents равно 2000 или 2 секунды.
Получение асинхронных уведомлений о событиях в VBScript
Вызовы скриптов для получения уведомлений о событиях по сути совпадают со всеми асинхронными вызовами с теми же проблемами безопасности. Дополнительные сведения см. в статье Асинхронный вызов с помощьюVBScript.
Получение асинхронных уведомлений о событиях в VBScript
Создайте объект приемника, используя WScript.CreateObject и указав prog-id "WbemScripting" и тип объекта SWbemSink. Объект-приемник получает уведомления.
Напишите подпрограмму для каждого события, которое требуется обрабатывать. В следующей таблице перечислены события SWbemSink.
Событие Значение OnObjectReady Сообщает о возврате объекта в приемник. Этот вызов возвращает один объект каждый раз до завершения операции. OnCompleted Сообщает о завершении асинхронного вызова. Это событие никогда не происходит, если операция неопределенна. OnObjectPut Сообщает о завершении асинхронной операции записи. Это событие возвращает путь к объекту экземпляра или сохраненного класса. OnProgress Сообщает о состоянии асинхронного вызова, выполняющегося в настоящий момент. Не все поставщики поддерживают промежуточные отчеты о ходе выполнения. Отмена Отменяет все невыполненные асинхронные операции, связанные с приемником объектов.
Следующий пример кода VBScript уведомляет об удалении процессов с интервалом опроса в 10 секунд. В этом скрипте подпрограмма SINK_OnObjectReady обрабатывает событие. В примере объект-приемник называется "Приемник", однако вы можете назвать этот объект как угодно.
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). Когда этот поток получает сообщение, поток уведомляет основное приложение.
Посвящая отдельный поток, вы позволяете вашему основному процессу выполнять другие задачи, ожидая прибытия события. Асинхронная доставка уведомлений повышает производительность, но может обеспечить меньшую безопасность, чем требуется. В C++ у вас есть возможность использовать интерфейс IWbemUnsecuredApartment или выполнять проверки доступа на дескрипторах безопасности. Дополнительные сведения см. в разделе Настройка безопасности для асинхронного вызова.
Настройка асинхронных уведомлений о событиях
Прежде чем инициализировать асинхронные уведомления, убедитесь, что параметры предотвращения отказа в памяти задаются правильно в Win32_WMISetting.
Определите, какие события вы хотите получить.
WMI поддерживает встроенные и внешние события. Внутреннее событие — это событие, предопределенное WMI, в то время как внешнее событие является событием, определенным сторонним поставщиком. Для получения дополнительной информации см. Определение типа события для получения.
В следующей процедуре описывается получение асинхронных уведомлений о событиях в C++.
Получение асинхронных уведомлений о событиях в C++
Настройте ваше приложение, вызвав функции 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; } // ... }
Создайте объект приемника с помощью интерфейса IWbemObjectSink.
WMI использует IWbemObjectSink для отправки уведомлений о событиях и отправке отчетов о состоянии асинхронной операции или уведомления о событии.
Зарегистрируйте потребителя событий с помощью вызова метода IWbemServices::ExecNotificationQueryAsync.
Убедитесь, что параметр pResponseHandler указывает на объект приемника, созданный на предыдущем шаге.
Цель регистрации — получать только необходимые уведомления. Получение излишних уведомлений приводит к потере времени на обработку и доставку и не позволяет в полной мере использовать возможности фильтрации WMI.
Однако временный потребитель может получать более одного типа событий. В этом случае временный потребитель должен выполнять отдельные вызовы к IWbemServices::ExecNotificationQueryAsync для каждого типа события. Например, пользователю может потребоваться уведомление о создании новых процессов (событие создания экземпляра или __InstanceCreationEvent) и о изменениях в определённых ключах реестра (событие реестра, например RegistryKeyChangeEvent). Поэтому потребитель делает один вызов к ExecNotificationQueryAsync для регистрации событий создания экземпляра и второй вызов к ExecNotificationQueryAsync для регистрации событий реестра.
Если вы решили создать потребитель событий, регистрирующийся для нескольких событий, следует избегать регистрации нескольких классов в одном приемнике. Вместо этого используйте отдельный приемник для каждого класса зарегистрированного события. Использование выделенной раковины упрощает обработку и помогает в обслуживании, позволяя отменить одну регистрацию без влияния на другие.
Выполняйте все необходимые действия в вашем обработчике событий.
Этот шаг должен содержать большую часть кода и включать такие действия, как отображение событий в пользовательском интерфейсе.
По завершении отмените регистрацию временного потребителя событий, вызвав событие IWbemServices::CancelAsyncCall.
Независимо от того, выполняется ли вызов CancelAsyncCall успешно или завершается сбоем, не удаляйте объект приемника до тех пор, пока число ссылок на объект не достигнет нуля. Дополнительные сведения см. в статье Вызов метода.