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

创建要检测的应用程序时,最佳做法是将提供程序作为组件包含在应用程序本身中。 这种做法允许 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 提供程序