WMI:MOF 基础






4.57/5 (8投票s)
托管对象格式的简短介绍。
引言
WBEM (Web-Based Enterprise Management) 是一个旨在实现企业环境管理标准化的行业倡议。WBEM 包含由 DMTF (Distributed Management Task Force) 开发和维护的一系列标准。WMI (Windows Management Instrumentation) 是 Microsoft 对 WBEM 的实现,被系统管理员和开发人员广泛用作管理 Windows 系统的工具。
WMI 使用 CIM (Common Information Model) 标准来表示各种 Windows 组件。CIM 是一种信息模型,用于描述可供管理的企业元素。CIM 有两个重要部分:CIM 规范和 CIM 模式。
CIM 模式包含一组代表可管理实体的类。它的核心模型包含最高抽象级别的类,如 CIM_ManagedElement
、CIM_Setting
和 CIM_Location
。这些类的派生用于组成 CIM 模式通用模型,每个模型描述一个不同的管理领域(例如,系统、用户、网络、应用程序等)。每个通用模型都用作特定平台扩展的基础,这些类代表您可以用于管理的具体、真实世界的元素。
CIM 规范定义了可用于表达管理模型的元素。其中一些元素是
- 模式。模式是一组具有单个所有者的类。每个类名都包含模式名。例如,
CIM_DataFile
、Win32_Process
和MSFT_WmiCoreEvent
类属于名为CIM
、Win32
和MSFT
的模式。 - 类。类是定义对象类共有的属性和方法的原型。
- 属性。属性描述类的数据。
- 方法。方法描述类的行为。
- 限定符。限定符提供有关类、属性和方法的附加信息。
CIM_DataFile.Name
属性有一个名为“Key
”的布尔类型限定符,其值为True
。
CIM 规范定义了模型的语法和规则,包括称为 MOF (Managed Object Format) 的 CIM 语法语言。在本文中,我将尝试介绍 MOF 用法的基本知识,并提供一些简单的示例。
Microsoft CIM 实现
WMI 是 Microsoft 对 CIM 的实现。要使模型正常工作,它需要包含两个组件:CIM 存储库和 CIMOM (CIM Object Manager)。存储库存储类定义,在某些情况下也存储实例定义(但这是一个例外——大多数实例定义由 WMI 提供程序动态检索)。对于 Windows 系统,存储库位于 %Windir%\System32\wbem\repository 目录(通常是 c:\windows\system32\wbem\repository\)。
CIMOM 是存储库和管理数据使用者之间的对象代理:它服务于消费者对数据检索、修改或添加到存储库的请求。Microsoft 对 CIMOM 的实现是一个名为 WinMgmt.exe 的 Windows 服务,也位于 %Windir%\System32\wbem 目录(或 c:\windows\system32\wbem\)。
WMI 消费者是与 WMI 交互的任何应用程序。WMI 提供程序是 DLL,它动态地将各种 Windows 子系统中的管理数据提供给 WMI。
使用示例
MOF 文件是一个文本文件,其中包含一系列类和实例定义。每个定义都以分号 (;) 结尾。MOF 文件还可以包含注释和编译指示指令。
要将 MOF 文件中包含的对象定义添加到 WMI 存储库,您需要一个名为 mofcomp.exe 的工具(也位于 %Windir%\System32\wbem 目录中)。Mofcomp.exe 支持许多控制其行为的命令行开关,但其基本语法是
mofcomp FileName.mof
如果没有错误,此命令会将 Filename.mof 中的类和实例定义添加到 WMI 存储库。
WMI 工具
Wbemtest.exe 是一个 WMI 测试工具,随每个 Windows 安装一起分发。您可以通过在命令提示符下键入“wbemtest”或从“开始”->“运行”->“wbemtest”来调用它。一个更用户友好的 WMI 工具名为 CIM Studio,可从 Microsoft 网站免费下载。如果您尚未安装 CIM Studio,我建议您安装它并在使用 WMI 时使用它。
启动 CIM Studio 后,会显示一个对话框,允许您选择要连接的 WMI 命名空间。连接后,会显示两个主窗格:右侧窗格是一个树形视图,表示所选命名空间中类的层次结构视图。在右侧窗格中,您可以查看类或实例详细信息。使用 CIM Studio,您可以添加、修改或删除 WMI 类或实例,编译 MOF 文件,从现有类生成 MOF 代码等。
创建 WMI 命名空间
WMI 存储库中的类以命名空间的层次结构组织。此层次结构的根是 Root
命名空间,它包含几个子命名空间,其中一个是众所周知的:CimV2
命名空间,WMI 操作的默认命名空间。尽管在使用本文提供的示例时可以使用 CimV2
命名空间,但最好创建一个新命名空间,您可以向其中添加类和实例,而不会影响 WMI 功能的其余部分。
这是将新命名空间添加到 WMI 的示例 MOF 代码
#pragma namespace("\\\\.\\Root")
instance of __Namespace
{
Name = "MOFNamespace";
};
要添加新命名空间,您需要执行以下操作
- 将上下文更改为您将要创建子命名空间的命名空间。为此,您可以使用
#pragma namespace
指令。在这种情况下,将在Root
下创建一个子命名空间。除了#pragma namespace
,您还可以使用 -N mofcomp 开关。 - 使用“
instance of
”关键字创建__Namespace
WMI 系统类的新实例。 - 将
Name
属性的新实例设置为新命名空间的名称。在本例中为“MOFNamespace
”。
使用 mofcomp.exe 编译上述 MOF 后,您将拥有一个新的 WMI 命名空间:Root\MOFNamespace
。如果您使用 Wbemtest 或 CIM Studio 浏览新创建的命名空间,您会发现它是空的,除了自动添加到每个新命名空间的一些 WMI 系统类。
删除 WMI 命名空间
使用新创建的命名空间 (MOFNamespace
) 进行测试后,您可以使用包含以下文本的 MOF 文件将其删除
#pragma namespace("\\\\.\\Root")
#pragma deleteinstance
("__Namespace.Name='MOFNamespace'", FAIL)
要删除 WMI 命名空间
- 使用
#pragma namespace
指令将 mofcomp 上下文更改为您要删除的命名空间的父命名空间。 - 使用
#pragma deleteinstance
指令删除实例。#deleteinstance
接受 WMI 对象路径作为参数,因此请为其提供要删除的__Namespace
实例的路径。
编译上述 MOF 文件将删除指定的命名空间及其所有内容,因此请谨慎使用。您需要严格遵守 WMI 对象路径,因此不能使用空格
"__Namespace.Name = 'MOFNamespace'"
使用 mofcomp.exe 编译时,将产生以下错误
An error occurred while processing item 1:
Error Number: 0x8004103a, Facility: WMI
Description: Invalid object path
Compiler returned error 0x80041001
如果您尝试删除的命名空间不存在且使用了 FAIL
,则会报告另一个错误
An error occurred while processing item 1:
0X80041002 Class, instance, or property '__Namespace.Name='MOFNamespace'' was not found.
Compiler returned error 0x80041001
创建基类
你们中的大多数人可能熟悉一些 WMI 类,例如 Win32_Process
、CIM_DataFile
和 Win32_Service
。这是一个示例 MOF 文件,可让您创建自己的 WMI 类
#pragma namespace("\\\\.\\Root\\MOFNamespace")
class Test_BaseClassWithNoProperties
{
};
- 使用
#pragma namespace
将 mofcomp 上下文更改为您要创建新类的命名空间。除了#pragma namespace
,您还可以使用 mofcomp -N 命令行开关。如果您不指定命名空间,新类将在Root\Cimv2
中创建。 - 使用“class”关键字让
mofcomp
知道您正在创建新类,后跟类名。按照惯例,类名由下划线分隔的两部分组成:类所属的模式和类名本身(例如,在CIM_DataFile
中,CIM 是模式名,DataFile 是类名)。 - 使用一对匹配的花括号将类体括起来。
上述 MOF 代码,当用 Mofcomp.exe 编译时,在 Root\MOFNamespace
下创建一个名为“Test_BaseClassWithNoProperties
”的新 WMI 类。由于我们没有为我们的类指定任何自定义属性,它只包含一组预定义的 WMI 系统属性。我们没有指定新类的父类,因此它将作为基类创建:它的 __Superclass
系统属性将为空。
向 WMI 类添加属性
这是一个创建类并为其添加一些属性的示例 MOF 代码
#pragma namespace("\\\\.\\Root\\MOFNamespace")
class Test_ClassWithProperties
{
[Key] uint32 KeyProperty;
string StringProperty;
boolean BoolProperty = false;
sint32 ArrayProperty [];
};
要向 WMI 类添加属性,在类体中,为每个属性指定以下格式的属性列表
- 将属性限定符列在方括号中。例如,如果您以:'
[Key]
' 开头属性声明,则该属性将被标记为该类的键属性。限定符是可选的。 - 声明属性数据类型。您可以在 CIM 规范中找到可用数据类型的列表。
- 声明属性名称。
- 如果属性有默认值,您可以在属性名称后指定该值。
- 如果属性是数组,请在属性名称后加一对方括号。要指定固定长度数组,请在方括号之间放置数组长度。
创建层次结构
CIM 规范遵循面向对象的范式——您可以通过在子类名称后指定父类名称来为给定类创建子类
class Test_DerivedClassTwo : Test_DerivedClassOne
{
boolean BoolProperty;
string ArrayProperty [];
};
使用 MOF 创建派生 WMI 类
- 使用“
class
”关键字,后跟新类名。 - 指定父类名,用冒号分隔。
- 在类体中,列出派生类的新属性。
在上面的示例中,Test_DerivedClassTwo
继承了所有 Test_DerivedClassOne
属性,并添加了两个。
创建关联类
关联是 CIM 模式的重要组成部分。要创建关联类,您需要创建一个用 Association
限定符标记的类,其中包含对感兴趣的实例类的引用。这是一个示例 MOF 代码
[Association : ToInstance]
class Test_AssociationClass
{
[Key] Test_GroupComponent ref GroupComponent;
[Key] Test_PartComponent ref PartComponent;
};
要创建关联类
- 在类声明前加上“
Association
”类限定符。 - 向类添加两个引用类型属性。引用指向关联类正在绑定的实例类(
Test_GroupComponent
,Test_PartComponent
)。
创建类实例
这是一个创建 WMI 类实例的示例 MOF
instance of Test_ClassWithProperties
{
KeyProperty = 5;
StringProperty = "String Value";
ArrayProperty = {1, 2, 3, 4, 5};
// BoolProperty is False by default
};
要创建类的实例
- 使用“
instance of
”关键字,后跟类名。 - 指定具有适当值的属性列表。如果属性有默认值,并且您没有设置其值,它将设置为默认值。数组值用花括号括起来。
结论
这里介绍的所有 WMI 类都是静态的,它们的实例及其定义都存储在 WMI 存储库中。这不常见:大多数 WMI 类是动态的——只有类定义存储在存储库中,而实例由底层 WMI 提供程序动态检索。
MOF 语法并不难:它由一系列类和实例定义组成,用于描述要移动到 CIMOM 的对象。但你为什么要使用它呢?对于大多数常见应用程序,标准的 WMI 用法,无论是通过 System.Management
.NET 命名空间还是 WMI 脚本库,都已足够,你根本不需要了解 MOF。另一方面,使用 MOF 创建动态 WMI 类,如果没有创建底层 WMI 提供程序(这很困难),则毫无用处。然而,在某些场景中,你可以使用上述技术来解决一些实际问题,我希望在接下来的几篇文章中展示其中一些。
最后说明
本文是对 MOF 的一个非常简短且不完整的介绍——更完整的文档可以在 DMTF 官方网站(我特别推荐 DMTF 教程)和 MSDN 中找到。为了进行比较,除了示例 MOF 文件,我还包含了 C# 和 VBScript 示例——对我来说,使用 MOF 比相应的 C# 或 VBScript 代码要容易得多。
最后,这里有一些有用的链接