在应用程序中包含提供程序

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

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

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

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

备注

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

本主题中的代码示例需要以下引用并 # 包含正确编译的语句。

#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 _ 身份验证 _ 级别 _ 默认值。 有关详细信息,请参阅 维护 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 提供程序