Выполнение асинхронного вызова с помощью C++
Приложения WMI, написанные на C++, могут выполнять асинхронные вызовы с помощью многих методов COM-интерфейса IWbemServices . Однако рекомендуемая процедура вызова метода WMI или метода поставщика заключается в использовании полусинхронных вызовов, так как полусинхронные вызовы более безопасны, чем асинхронные вызовы. Дополнительные сведения см. в разделах Выполнение полусинхронного вызова с помощью C++ и Настройка безопасности в асинхронном вызове.
В следующей процедуре описывается, как выполнить асинхронный вызов с помощью приемника в процессе.
Выполнение асинхронного вызова с помощью C++
Реализуйте интерфейс IWbemObjectSink .
Все приложения, которые выполняют асинхронные вызовы, должны реализовывать IWbemObjectSink. Временные потребители событий также реализуют IWbemObjectSink для получения уведомлений о событиях.
Войдите в целевое пространство имен WMI.
Приложения всегда должны вызывать com-функцию CoInitializeSecurity на этапе инициализации. Если они не делают этого перед асинхронным вызовом, WMI освобождает приемник приложения без завершения асинхронного вызова. Дополнительные сведения см. в разделе Инициализация COM для приложения WMI.
Задайте безопасность для приемника.
Асинхронные вызовы создают ряд проблем безопасности, с которыми может потребоваться столкнуться, например, разрешение доступа WMI к приложению. Дополнительные сведения см. в разделе Настройка безопасности при асинхронном вызове.
Выполните асинхронный вызов.
Метод возвращает немедленно с кодом WBEM_S_NO_ERROR успешного выполнения. Приложение может продолжить выполнение других задач, ожидая завершения операции. WMI передает данные в приложение, вызывая методы в реализации IWbemObjectSink приложения.
При необходимости периодически проверка свою реализацию для обновлений.
Приложения могут получать уведомления о промежуточном состоянии, задав параметру lFlags в асинхронном вызове значение WBEM_FLAG_SEND_STATUS. WMI сообщает о состоянии вызова, задав параметру lFlagsIWbemObjectSinkзначение WBEM_STATUS_PROGRESS.
При необходимости можно отменить вызов до завершения обработки WMI, вызвав метод IWbemServices::CancelCallAsync .
Метод CancelAsyncCall отменяет асинхронную обработку, немедленно освобождая указатель на интерфейс IWbemObjectSink и гарантируя, что указатель будет освобожден до возврата CancelAsyncCall .
Если вы используете объект-оболочку, реализующий интерфейс IUnsecured для размещения IWbemObjectSink, могут возникнуть некоторые дополнительные сложности. Поскольку приложение должно передать тот же указатель на CancelAsyncCall , который был передан в исходном асинхронном вызове, приложение должно удерживать объект-оболочку, пока не станет ясно, что отмена не требуется. Дополнительные сведения см. в разделе Настройка безопасности при асинхронном вызове.
По завершении очистите указатели и завершите работу приложения.
WMI предоставляет окончательный вызов состояния с помощью метода SetStatus .
Примечание
После отправки окончательного обновления состояния WMI освобождает приемник объекта, вызывая метод Release для класса, реализующего интерфейс IWbemObjectSink . В предыдущем примере это метод QuerySink::Release . Если вы хотите контролировать время существования объекта приемника, можно реализовать приемник с начальным количеством ссылок 1 (1).
Если клиентское приложение передает один и тот же интерфейс приемника в двух разных перекрывающихся асинхронных вызовах, WMI не гарантирует порядок обратного вызова. Клиентское приложение, выполняющее перекрывающиеся асинхронные вызовы, должно либо передавать различные объекты приемника, либо сериализовать вызовы.
В следующем примере требуются следующие операторы reference и #include.
#include <iostream>
using namespace std;
#pragma comment(lib, "wbemuuid.lib")
#include <wbemidl.h>
В следующем примере описывается создание асинхронного запроса с помощью метода ExecQueryAsync , но не создание параметров безопасности и не освобождение объекта IWbemObjectSink . Дополнительные сведения см. в разделе Настройка безопасности при асинхронном вызове.
// Set input parameters to ExecQueryAsync.
BSTR QueryLang = SysAllocString(L"WQL");
BSTR Query = SysAllocString(L"SELECT * FROM MyClass");
// Create IWbemObjectSink object and set pointer.
QuerySink *pSink = new QuerySink;
IWbemServices* pSvc = 0;
// Call ExecQueryAsync.
HRESULT hRes = pSvc->ExecQueryAsync(QueryLang,
Query,
0,
NULL,
pSink);
// Check for errors.
if (hRes)
{
printf("ExecQueryAsync failed with = 0x%X\n", hRes);
SysFreeString(QueryLang);
SysFreeString(Query);
delete pSink;
return ERROR;
}
Примечание
Приведенный выше код не компилируется без ошибок, так как класс QuerySink не определен. Дополнительные сведения о QuerySink см. в разделе IWbemObjectSink.
Связанные темы