Поделиться через


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

Приложения WMI, написанные на C++, могут выполнять асинхронные вызовы с помощью многих методов интерфейса IWbemServices COM. Однако рекомендуемой процедурой вызова метода 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 сообщает о состоянии вызова, задавая параметру lFlags интерфейса IWbemObjectSink значение WBEM_STATUS_PROGRESS.

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

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

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

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

    WMI предоставляет окончательный вызов состояния через метод SetStatus.

    Заметка

    После отправки окончательного обновления состояния WMI освобождает приемник объекта, вызвав метод Release для класса, реализующего интерфейс IWbemObjectSink. В предыдущем примере это метод QuerySink::Release. Если вы хотите контролировать время существования объекта приемника, можно реализовать приемник с начальным счетчиком ссылок, равным единице.

     

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

В следующем примере требуется следующая ссылка и #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.

 

вызов метода