Fazer uma chamada assíncrona com C++

Os aplicativos do WMI escritos em C++ podem fazer chamadas assíncronas usando muitos dos métodos da interface COM IWbemServices. No entanto, o procedimento recomendado para chamar um método do WMI ou um método de provedor é usar chamadas semissíncronas porque elas são mais seguras do que chamadas assíncronas. Para obter mais informações, confira Fazer uma chamada semissíncrona com C++ e Definir a segurança em uma chamada assíncrona.

O procedimento a seguir descreve como fazer uma chamada assíncrona usando o coletor em seu processo.

Para fazer uma chamada assíncrona usando C++

  1. Implemente a interface IWbemObjectSink.

    Todos os aplicativos que fazem chamadas assíncronas devem implementar IWbemObjectSink. Os consumidores de eventos temporários também implementam IWbemObjectSink para receber notificação de eventos.

  2. Faça logon no namespace do WMI de destino.

    Os aplicativos sempre precisam chamar a função COM CoInitializeSecurity durante a fase de inicialização. Se eles não fizerem isso antes de fazer uma chamada assíncrona, o WMI liberará o coletor do aplicativo sem concluir a chamada assíncrona. Para obter mais informações, confira Inicializar o COM para um aplicativo do WMI.

  3. Defina a segurança do coletor.

    Chamadas assíncronas criam uma variedade de problemas de segurança com os quais talvez seja necessário lidar, por exemplo, a permissão para o WMI acessar seu aplicativo. Para obter mais informações, confira Configurar a segurança em uma chamada assíncrona.

  4. Faça a chamada assíncrona.

    O método retorna imediatamente com o código de êxito WBEM_S_NO_ERROR. O aplicativo pode prosseguir com outras tarefas enquanto aguarda a conclusão da operação. O WMI responde ao aplicativo chamando métodos na implementação IWbemObjectSink do seu aplicativo.

  5. Se necessário, verifique periodicamente se há atualizações para sua implementação.

    Os aplicativos podem receber notificação de status intermediários definindo o parâmetro lFlags na chamada assíncrona para WBEM_FLAG_SEND_STATUS. O WMI relata o status de sua chamada definindo o parâmetro lFlags de IWbemObjectSink como WBEM_STATUS_PROGRESS.

  6. Se necessário, você pode cancelar a chamada antes que o WMI conclua o processamento chamando o método IWbemServices::CancelCallAsync.

    O método CancelAsyncCall cancela o processamento assíncrono liberando imediatamente o ponteiro para a interface IWbemObjectSink e garante que o ponteiro seja liberado antes do retorno de CancelAsyncCall.

    Se você estiver usando um objeto wrapper implementando a interface IUnsecured para hospedar IWbemObjectSink, poderá encontrar algumas complicações adicionais. Como o aplicativo deve passar o mesmo ponteiro para CancelAsyncCall que foi passado na chamada assíncrona original, o aplicativo deverá manter o objeto wrapper até ficar claro que o cancelamento não é necessário. Para obter mais informações, confira Configurar a segurança em uma chamada assíncrona.

  7. Quando terminar, limpe os ponteiros e desligue o aplicativo.

    O WMI fornece a chamada final status por meio do método SetStatus.

    Observação

    Depois de enviar a atualização final de status, o WMI liberará o coletor de objetos chamando o método Release para a classe que implementa a interface IWbemObjectSink. No exemplo anterior, esse é o método QuerySink::Release. Se você quiser ter controle sobre o tempo de vida do objeto coletor, poderá implementar o coletor com uma contagem de referência inicial igual a um (1).

     

    Se um aplicativo cliente passar a mesma interface de coletor em duas chamadas assíncronas sobrepostas diferentes, o WMI não garantirá a ordem do retorno de chamada. Um aplicativo cliente que faz chamadas assíncronas sobrepostas deve passar objetos de coletor diferentes ou serializar as chamadas.

O exemplo a seguir requer a seguinte referência e instruções #include.

#include <iostream>
using namespace std;
#pragma comment(lib, "wbemuuid.lib")
#include <wbemidl.h>

O exemplo a seguir descreve como fazer uma consulta assíncrona usando o método ExecQueryAsync, mas não cria configurações de segurança nem libera o objeto IWbemObjectSink. Para obter mais informações, confira Configurar a segurança em uma chamada assíncrona.

// 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;
}

Observação

O código acima não é compilado sem erro porque a classe QuerySink não foi definida. Para obter mais informações sobre a QuerySink, consulte IWbemObjectSink.

 

Chamar um método