创建 WMI 基类

为 WMI 提供程序创建新 WMI 基类的建议方式是在托管对象格式 (MOF) 文件中创建。 还可以使用适用于 WMI 的 COM API 创建基类。 虽然你可以在脚本中创建基类或派生类,但如果提供程序不向该类及其子类提供数据,则该类就没有作用。

本主题包括以下部分:

使用 MOF 创建基类

WMI 类通常依赖于继承。 在创建基类之前,请检查分布式管理任务组 (DMTF) 提供的通用信息模型 (CIM) 类。

如果许多派生类使用相同的属性,请将这些属性和方法放入基类。 可以在 WMI 类中定义的最大属性数为 1024。

创建基类时,请遵守下面列出的类名准则:

  • 同时使用大写和小写字母。

  • 类名以字母开头。

  • 不要使用前导或尾部下划线。

  • 将所有剩余字符定义为字母、数字或下划线。

  • 使用一致的命名约定。

    虽然不要求这样,但合理的类命名约定是使用下划线联接两个组成部分。 如果可能,供应商名称应构成名称的前半部分,描述性类名应构成后半部分。

注意

在执行提供程序期间无法更改类。 必须停止活动,更改类,然后重启 Windows 管理服务。 目前无法检测类更改。

 

在 MOF 中,创建基类的方式是使用 class 关键字为该类命名,但不指明父类。

使用 MOF 代码创建基类

  1. 使用 class 关键字和新类的名称,后接一对大括号和一个分号。 在大括号之间为类添加属性和方法。 提供了以下代码示例。

    以下代码示例演示如何定义基类。

    class MyClass_BaseDisk
    {
    };
    

    以下代码示例演示基类的错误定义。

    class MyClass_BaseDisk : CIM_LogicalDisk
    {
    };
    
  2. 在 class 关键字之前添加任何类限定符以修改类的使用方式。 将限定符放在方括号之间。 有关用于修改类的限定符的详细信息,请参阅 WMI 限定符。 使用 Abstract 限定符指示不能直接创建此类的实例。 抽象类通常用于定义多个派生类使用的属性或方法。 有关详细信息,请参阅创建派生类

    以下代码示例将类定义为抽象类,并定义将提供数据的提供程序。 ToSubClass 限定符 flavor 指示 Provider 限定符中的信息由派生类继承。

    [Abstract, Provider("MyProvider") : ToSubClass]
    class MyClass_BaseDisk
    {
    };
    
  3. 在属性或方法名称前面的方括号中添加类的属性和方法。 有关详细信息,请参阅添加属性创建方法。 可以使用 MOF 限定符修改这些属性和方法。 有关详细信息,请参阅添加限定符

    以下代码示例演示如何使用 MOF 限定符修改属性和方法。

    [read : ToSubClass, key : ToSubClass ] string DeviceID;
      [read : ToSubClass] uint32 State;
      [read : ToSubclass, write : ToSubClass] uint64 LimitUsers;
    
  4. 使用扩展名 .mof 保存 MOF 文件。

  5. 通过对文件运行 Mofcomp.exe 向 WMI 注册类。

    mofcomp.exe newmof.mof

    如果不使用 -N 开关或预处理器命令 #pragma namespace 指定命名空间,则编译的 MOF 类将存储在存储库中的 root\default 命名空间中。 有关详细信息,请参阅 mofcomp

以下代码示例结合了前面过程中讨论的 MOF 代码示例,演示如何使用 MOF 在 root\cimv2 命名空间中创建基类。

#pragma namespace("\\\\.\\Root\\cimv2")

[Abstract, Provider("MyProvider") : ToSubClass]
class MyClass_BaseDisk
{
  [read : ToSubClass, key : ToSubClass ] string DeviceID;
  [read : ToSubClass] uint32 State;
  [read : ToSubClass, write : ToSubClass] uint64 LimitUsers;
};

有关详细信息,请参阅创建派生类,其中提供了从此基类派生的动态类示例。

使用 C++ 创建基类

使用 WMI API 创建基类的过程主要是执行一系列 Put 命令来定义该类并将其注册到 WMI。 此 API 的主要用途是使客户端应用程序能够创建基类。 但是,你也可以让提供程序使用此 API 创建基类。 例如,如果你认为提供程序的 MOF 代码不会正确安装,可以指示提供程序在 WMI 存储库中自动创建正确的类。 有关提供程序的详细信息,请参阅编写类提供程序

注意

在执行提供程序期间无法更改类。 必须停止活动,更改类,然后重启 Windows 管理服务。 目前无法检测类更改。

 

代码需要以下引用才能正确编译。

#include <wbemidl.h>

可以使用适用于 WMI 的 COM API 以编程方式创建新的基类。

使用 WMI API 创建新的基类

  1. 通过调用 IWbemServices::GetObject 方法并将 strObjectPath 参数设置为 null 值来检索新类的定义。

    以下代码示例演示如何检索新类的定义。

    IWbemServices* pSvc = 0;
    IWbemContext* pCtx = 0;
    IWbemClassObject* pNewClass = 0;
    IWbemCallResult* pResult = 0;
    HRESULT hRes = pSvc->GetObject(0, 0, pCtx, &pNewClass, &pResult);
    
  2. 通过调用 IWbemClassObject::Put 方法设置 __CLASS 系统属性来建立类名称。

    以下代码示例演示如何通过设置 __CLASS 系统属性来命名类。

    VARIANT v;
    VariantInit(&v);
    V_VT(&v) = VT_BSTR;
    
    V_BSTR(&v) = SysAllocString(L"Example");
    BSTR Class = SysAllocString(L"__CLASS");
    pNewClass->Put(Class, 0, &v, 0);
    SysFreeString(Class);
    VariantClear(&v);
    
  3. 通过调用 IWbemClassObject::Put 创建一个或多个键属性。

    以下代码示例演示如何创建 Index 属性,该属性在步骤 4 中标记为键属性。

      BSTR KeyProp = SysAllocString(L"Index");
      pNewClass->Put(KeyProp, 0, NULL, CIM_STRING);
    
  4. 通过依次调用 IWbemClassObject::GetPropertyQualifierSet 方法和 IWbemQualifierSet::Put 方法,将 Key 标准限定符附加到键属性。

    以下代码示例演示如何将 Key 标准限定符附加到键属性。

      IWbemQualifierSet *pQual = 0;
      pNewClass->GetPropertyQualifierSet(KeyProp, &pQual);
      SysFreeString(KeyProp);
    
      V_VT(&v) = VT_BOOL;
      V_BOOL(&v) = VARIANT_TRUE;
      BSTR Key = SysAllocString(L"Key");
    
      pQual->Put(Key, &v, 0);   // Flavors not required for Key 
      SysFreeString(Key);
    
      // No longer need the qualifier set for "Index"
      pQual->Release();   
      VariantClear(&v);
    
  5. 使用 IWbemClassObject::Put 创建类的其他属性。

    以下代码示例说明如何创建其他属性。

      V_VT(&v) = VT_BSTR;
      V_BSTR(&v) = SysAllocString(L"<default>");
      BSTR OtherProp = SysAllocString(L"OtherInfo");
      pNewClass->Put(OtherProp, 0, &v, CIM_STRING);
      SysFreeString(OtherProp);
      VariantClear(&v);
    
      OtherProp = SysAllocString(L"IntVal");
      pNewClass->Put(OtherProp, 0, NULL, CIM_SINT32); // NULL is default
      SysFreeString(OtherProp);
    
  6. 通过调用 IWbemServices::PutClass 注册新类。

    由于在注册新类后无法定义键和索引,因此请确保在调用 PutClass 之前已定义所有属性。

    以下代码示例说明如何注册新类。

      hRes = pSvc->PutClass(pNewClass, 0, pCtx, &pResult);
      pNewClass->Release();
    

以下代码示例结合了前面过程中讨论的代码示例,演示如何使用 WMI API 创建基类。

void CreateClass(IWbemServices *pSvc)
{
  IWbemClassObject *pNewClass = 0;
  IWbemContext *pCtx = 0;
  IWbemCallResult *pResult = 0;

  // Get a class definition. 
  // ============================
  HRESULT hRes = pSvc->GetObject(0, 0, pCtx, &pNewClass, &pResult);
  VARIANT v;
  VariantInit(&v);

  // Create the class name.
  // ============================
  V_VT(&v) = VT_BSTR;
  V_BSTR(&v) = SysAllocString(L"Example");
  BSTR Class = SysAllocString(L"__CLASS");
  pNewClass->Put(Class, 0, &v, 0);
  SysFreeString(Class);
  VariantClear(&v);

  // Create the key property. 
  // ============================
  BSTR KeyProp = SysAllocString(L"Index");
  pNewClass->Put(KeyProp, 0, NULL, CIM_STRING);

  // Attach Key qualifier to mark the "Index" property as the key.
  // ============================
  IWbemQualifierSet *pQual = 0;
  pNewClass->GetPropertyQualifierSet(KeyProp, &pQual);
  SysFreeString(KeyProp);

  V_VT(&v) = VT_BOOL;
  V_BOOL(&v) = VARIANT_TRUE;
  BSTR Key = SysAllocString(L"Key");

  pQual->Put(Key, &v, 0);   // Flavors not required for Key 
  SysFreeString(Key);

  // No longer need the qualifier set for "Index"
  pQual->Release();     
  VariantClear(&v);

  // Create other properties.
  // ============================
  V_VT(&v) = VT_BSTR;
  V_BSTR(&v) = SysAllocString(L"<default>");
  BSTR OtherProp = SysAllocString(L"OtherInfo");
  pNewClass->Put(OtherProp, 0, &v, CIM_STRING);
  SysFreeString(OtherProp);
  VariantClear(&v);

  OtherProp = SysAllocString(L"IntVal");
  pNewClass->Put(OtherProp, 0, NULL, CIM_SINT32); // NULL is default
  SysFreeString(OtherProp);
  
  // Register the class with WMI
  // ============================
  hRes = pSvc->PutClass(pNewClass, 0, pCtx, &pResult);
  pNewClass->Release();
}

创建类