在应用程序中合并提供程序

创建要检测的应用程序时,最佳做法是将提供程序作为组件包含在应用程序本身中。 这样做的话,Windows Management Instrumentation (WMI) 可直接与服务提供程序交互,而不是通过程序 API 间接交互。 将提供程序与 WMI 分离还使应用程序控制提供程序生存期而不是 WMI。 若要详细了解如何编写在 WMI 进程中运行的提供程序,请参阅通过编写提供程序向 WMI 提供数据。 若要详细了解提供程序的托管模型和安全设置,请参阅提供程序托管和安全性

下图说明了 WMI、分离的提供程序和应用程序之间的关系。

wmi、分离的提供程序和应用程序之间的关系

有关分离的提供程序方法的详细信息,请参阅 IWbemDecoupledRegistrarIWbemDecoupledBasicEventProvider

注意

分离的提供程序支持实例、方法、事件提供程序和事件使用者。 它不支持类提供程序和属性提供程序。 有关详细信息,请参阅编写类提供程序编写属性提供程序

 

本主题中的代码示例需要以下引用和 #include 语句才能正确编译。

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

以下过程使用 C++ 代码示例来说明如何将分离的提供程序合并到应用程序中。 应用程序的初始化方法执行以下步骤,以便 WMI 仅与已注册的分离提供程序交互。

在 C++ 应用程序中实现分离的提供程序

  1. 初始化 COM 库,供调用线程使用。

    以下代码示例显示了如何初始化 COM 库。

    HRESULT hr = S_OK ;
    hr = CoInitializeEx (0, COINIT_MULTITHREADED );
    
  2. 设置默认进程安全级别。

    此级别建立其他进程访问客户端进程信息所需的安全级别。 身份验证级别应为 RPC_C_AUTHN_LEVEL_DEFAULT。 有关详细信息,请参阅维护 WMI 安全性

    以下代码示例显示如何设置默认安全级别。

    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. 注册分离的提供程序注册器。

    以下代码示例显示如何注册分离的提供程序注册器。

    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. 注册分离的事件提供程序。

    以下代码示例显示如何注册分离的事件提供程序。

    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. 需要调用 WMI 才能使用提供程序的功能。 有关详细信息,请参阅处理类和实例信息。 若要详细了解提供程序是否为来自脚本或应用程序的数据请求提供服务,请参阅模拟客户端

在终止之前,应用程序必须自行清理。 以下过程说明如何注销分离的提供程序,以便 WMI 不会尝试查询该提供程序来获取信息。

以下过程说明如何注销分离的提供程序。

注销分离的提供程序

  1. 注销并释放注册器。

    以下代码示例显示如何注销和释放注册器。

    myRegistrar->UnRegister();
    myRegistrar->Release();
    
  2. 注销并释放事件提供程序。

    以下代码示例显示如何注销和释放事件提供程序。

    myEvtRegistrar->UnRegister();
    myEvtRegistrar->Release();
    
  3. 清理 COM 服务器。

    以下代码示例显示如何取消初始化 COM 库。

    CoUninitialize();
    

设置命名空间安全描述符

保护提供程序

开发 WMI 提供程序