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

创建要检测的应用程序时,最佳做法是将提供程序作为组件包含在应用程序本身中。 这种做法允许Windows Management Instrumentation (WMI) 直接与服务提供商交互,而不是通过程序 API 间接交互。 将提供程序与 WMI 分离也使应用程序控制提供程序的生命周期,而不是 WMI。 有关编写在 WMI 进程中运行的提供程序的详细信息,请参阅 通过编写提供程序向 WMI 提供数据。 有关提供程序的托管模型和安全设置的详细信息,请参阅 提供程序托管和安全性

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

relationship between wmi, decoupled provider, and application

有关分离提供程序方法的详细信息,请参阅 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();
    

设置 Namepace 安全描述符

保护提供商

开发 WMI 提供程序