Incorporar um provedor em um aplicativo

Ao criar um aplicativo que deve ser instrumentado, a melhor prática é incluir o provedor como um componente dentro do próprio aplicativo. Essa prática permite que a WMI (Instrumentação de Gerenciamento do Windows) interaja diretamente com o provedor do serviço, em vez de indiretamente, por meio da API do programa. Ao desacoplar o provedor do WMI, o aplicativo assume o controle do tempo de vida do provedor em vez do WMI. Para obter mais informações sobre como escrever um provedor executado no processo do WMI, confira Fornecer dados para o WMI escrevendo um provedor. Para obter mais informações sobre o modelo de hospedagem e as configurações de segurança do provedor, confira Hospedagem e segurança do provedor.

O diagrama a seguir ilustra a relação entre o WMI, um provedor desacoplado e um aplicativo.

relação entre wmi, provedor desacoplado e aplicativo

Para obter mais informações sobre métodos de provedor desacoplados, consulte IWbemDecoupledRegistrar e IWbemDecoupledBasicEventProvider.

Observação

O provedor desacoplado dá suporte a instância, método, provedores de eventos e consumidores de eventos. Ele não dá suporte a provedores de classe e propriedade. Para obter mais informações, confira Escrever um provedor de classe e Escrever um provedor de propriedades.

 

Os exemplos de código neste tópico exigem que as referências e instruções #include a seguir sejam compiladas corretamente.

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

O procedimento a seguir usa exemplos de código C++ para descrever como incorporar um provedor desacoplado em seu aplicativo. O método de inicialização do aplicativo executa as etapas a seguir para que o WMI interaja apenas com um provedor desacoplado registrado.

Para implementar um provedor desacoplado em um aplicativo C++

  1. Inicialize a biblioteca COM para ser usada pelo thread de chamada.

    O exemplo de código a seguir mostra como inicializar a biblioteca COM.

    HRESULT hr = S_OK ;
    hr = CoInitializeEx (0, COINIT_MULTITHREADED );
    
  2. Defina o nível de segurança do processo padrão.

    Esse nível estabelece o nível de segurança exigido de outros processos para acessar as informações do processo do cliente. O nível de autenticação deve ser RPC_C_AUTHN_LEVEL_DEFAULT. Para obter mais informações, confira Manutenção da segurança do WMI.

    O exemplo de código a seguir mostra como definir o nível de segurança padrão.

    hr = CoInitializeSecurity (NULL, 
        -1, 
        NULL, 
        NULL,
        RPC_C_AUTHN_LEVEL_DEFAULT,
        RPC_C_IMP_LEVEL_IMPERSONATE,
        NULL, 
        EOAC_DYNAMIC_CLOAKING, 
        NULL);
    
    if (FAILED(hr))
    {
      CoUninitialize();
      cout << "Failed to initialize security. Error code = 0x"
           << hex << hr << endl;
      return;
    }
    
  3. Registre o registrador de provedor desacoplado.

    O exemplo de código a seguir mostra como registrar o registrador de provedor desacoplado.

    CLSID CLSID_WbemDecoupledRegistrar;
    IID IID_IWbemDecoupledRegistrar;
    IWbemDecoupledRegistrar *myRegistrar = NULL;
    
    hr = CoCreateInstance(CLSID_WbemDecoupledRegistrar,
                          NULL,
                          CLSCTX_INPROC_SERVER,
                          IID_IWbemDecoupledRegistrar,
                          (void**)&myRegistrar);
    if (SUCCEEDED(hr))
    {
        IUnknown *pIUnknown = NULL;
        // CMyProv is the class added for WMI instance / event provider
        HRESULT hr = CMyProv::CreateInstance(NULL,&pIUnknown);
        if ( SUCCEEDED(hr))
        {
            hr = myRegistrar->Register(0,
                NULL,
                NULL,
                NULL,
                L"root\\cimv2",
                L"DecoupledInstanceProvider",
                pIUnknown);
    
                pIUnknown->Release();
        }
    }
    
    if (FAILED (hr))
    {
        if ( myRegistrar )
        {
            myRegistrar->Release () ;
        }
    }
    
  4. Registre o provedor de eventos desacoplado.

    O exemplo de código a seguir mostra como registrar o provedor de eventos desacoplado.

    IWbemDecoupledBasicEventProvider *myEvtRegistrar;
    
    // -- Create an instance of IWbemDecoupledEventProvider
    hr = CoCreateInstance(CLSID_WbemDecoupledBasicEventProvider,
                          NULL,
                          CLSCTX_INPROC_SERVER,
                          IID_IWbemDecoupledBasicEventProvider,
                          (void**)&myEvtRegistrar);
    
    if (SUCCEEDED(hr))
    {
       // -- Register the DecoupledEventProvider
       hr = myEvtRegistrar->Register(0,
                                     NULL,
                                     NULL,
                                     L"root\\cimv2",
                                     L"DecoupledEventProvider",
                                     NULL, NULL);
       if (SUCCEEDED(hr))
       {
          IWbemServices *pService = NULL;
          hr = myEvtRegistrar->GetService (0, NULL, &pService);
          if (SUCCEEDED(hr))
          {
             IWbemObjectSink *pSink = NULL;
             hr = myEvtRegistrar->GetSink ( 0, NULL, &pSink );
             if (SUCCEEDED(hr))
             {
                // Provide events
             }
          }
       } 
    }
    
  5. Faça as chamadas ao WMI exigidas pela funcionalidade do provedor. Para obter mais informações, confira Manipular informações de classe e instância. Para saber se o provedor atende a uma solicitação de dados de um script ou aplicativo, confira Representar um cliente.

Pouco antes de terminar, o aplicativo deverá limpar as informações que utilizou. O procedimento a seguir descreve como cancelar o registro do provedor desacoplado para que o WMI não tente consultá-lo para obter informações.

O procedimento a seguir descreve como cancelar o registro do provedor desacoplado.

Para cancelar o registro do provedor desacoplado

  1. Cancele o registro e libere o registrador.

    O exemplo de código a seguir mostra como cancelar o registro e liberar o registrador.

    myRegistrar->UnRegister();
    myRegistrar->Release();
    
  2. Cancele o registro e libere o provedor de eventos.

    O exemplo de código a seguir mostra como cancelar o registro e liberar o provedor de eventos.

    myEvtRegistrar->UnRegister();
    myEvtRegistrar->Release();
    
  3. Limpe o servidor COM.

    O exemplo de código a seguir mostra como parar a biblioteca COM.

    CoUninitialize();
    

Definir descritores de segurança de namespace

Como proteger seu provedor

Desenvolver um provedor do WMI