Выполнение асинхронного вызова с помощью C++

Приложения WMI, написанные на C++, могут выполнять асинхронные вызовы с помощью многих методов COM-интерфейса IWbemServices . Однако рекомендуемая процедура вызова метода WMI или метода поставщика заключается в использовании полусинхронных вызовов, так как полусинхронные вызовы более безопасны, чем асинхронные вызовы. Дополнительные сведения см. в разделах Выполнение полусинхронного вызова с помощью C++ и Настройка безопасности в асинхронном вызове.

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

Выполнение асинхронного вызова с помощью C++

  1. Реализуйте интерфейс IWbemObjectSink .

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

  2. Войдите в целевое пространство имен WMI.

    Приложения всегда должны вызывать com-функцию CoInitializeSecurity на этапе инициализации. Если они не делают этого перед асинхронным вызовом, WMI освобождает приемник приложения без завершения асинхронного вызова. Дополнительные сведения см. в разделе Инициализация COM для приложения WMI.

  3. Задайте безопасность для приемника.

    Асинхронные вызовы создают ряд проблем безопасности, с которыми может потребоваться столкнуться, например, разрешение доступа WMI к приложению. Дополнительные сведения см. в разделе Настройка безопасности при асинхронном вызове.

  4. Выполните асинхронный вызов.

    Метод возвращает немедленно с кодом WBEM_S_NO_ERROR успешного выполнения. Приложение может продолжить выполнение других задач, ожидая завершения операции. WMI передает данные в приложение, вызывая методы в реализации IWbemObjectSink приложения.

  5. При необходимости периодически проверка свою реализацию для обновлений.

    Приложения могут получать уведомления о промежуточном состоянии, задав параметру lFlags в асинхронном вызове значение WBEM_FLAG_SEND_STATUS. WMI сообщает о состоянии вызова, задав параметру lFlagsIWbemObjectSinkзначение WBEM_STATUS_PROGRESS.

  6. При необходимости можно отменить вызов до завершения обработки WMI, вызвав метод IWbemServices::CancelCallAsync .

    Метод CancelAsyncCall отменяет асинхронную обработку, немедленно освобождая указатель на интерфейс IWbemObjectSink и гарантируя, что указатель будет освобожден до возврата CancelAsyncCall .

    Если вы используете объект-оболочку, реализующий интерфейс IUnsecured для размещения IWbemObjectSink, могут возникнуть некоторые дополнительные сложности. Поскольку приложение должно передать тот же указатель на CancelAsyncCall , который был передан в исходном асинхронном вызове, приложение должно удерживать объект-оболочку, пока не станет ясно, что отмена не требуется. Дополнительные сведения см. в разделе Настройка безопасности при асинхронном вызове.

  7. По завершении очистите указатели и завершите работу приложения.

    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.

 

Вызов метода