WMI 脚本入门:第四部分

比较类与托管资源

大部分 WMI 属性和方法是合理命名的。例如,如 8 所示,如果您将由 Win32_Service 类定义的属性和方法与服务的属性对话框相比,就不难推断出 Win32_Service.NameWin32_Service.DisplayNameWin32_Service.Descritpion 可能会包含什么。

scripting08132002_fig8thumb

8:服务属性对话框与 Win32_Service 类属性及方法

那么我们为什么要关心所有这些内容?因为类决定了您能够(或不能)用 WMI做什么。如果有一个服务的类,您就可以管理服务;如果没有,您就不能这样做。属性和方法是很重要的,这是因为 WMI 的版本在操作系统间是有区别的。Windows XP 中的 Win32_ComputerSystem 类有很多新的属性和方法,而它们在 Windows 2000 中的 Win32_ComputerSystem 类中是没有的。您必须知道 WMI 的详细信息,因为不同于 ADSI,为了让工作顺利进行,WMI 属性和方法必须可用于目标计算机。

如何确定一台远程 Windows 计算机是否支持某个属性或方法?请检查类定义。

检索类定义

与 WMI 中所有东西一样,有无数方法可以检索托管资源的类定义。好吧,也许我们有点夸张了,但是也足以说,有许多为每个用户界面首选项提供解决方案的方法。如果您想要检索文本文件,只需分割 MOF 文件。如果您更喜欢命令行,就使用 WMI 命令行工具 wmic.exe(仅限 Windows XP)。如果您乐于将时间花在图形化工具上,就使用 WMI 测试器 (wbemtest.exe) 或 CIM Studio。或者如果您喜欢我们,就使用 WMI 脚本库。

使用 WMI 脚本库,您可以通过三种不同的方法检索托管资源类定义。

1.

您可以使用 SWbemObjectQualifiers_Properties_Methods_ 属性检索类信息。

2.

您可以使用 SWbemObjectGetObjectText_ 方法来检索以 MOF 语法格式化的类定义。

3.

您可以使用 SWbemObjectExGetText_ 方法来检索以 XML 格式化的类定义(仅限 Windows XP 和 Windows Server 2003)。

让我们简要地看看每个脚本方案,就此结束今天的内容。

使用 SWbemObject Properties_、Methods_ 和 Qualifiers_

清单 9、10 和 11 演示了如何使用 WMI 脚本库的 SWbemObjectProperties_Methods_Qualifiers_ 属性来检索关于 Win32_Service 类的信息。我们将研究清单 9,然后指出清单 10 和清单 11 中的不同之处,因为三个脚本使用了相同的基本方法。

清单 9 从初始化三个变量开始,它们是:strComputer、strNameSpace 和 strClass 分配给 strComputer 的值是启用了 WMI 的目标计算机。分配给 strNameSpace 的值是要连接到的命名空间。分配给 strClass 的值是在目标命名空间中的类的名称,此命名空间的属性将被检索和显示。将这三个值分开到多个变量中会使其他计算机、命名空间和类对脚本的重新使用变得简单。事实上,您可以用 Windows 脚本宿主 (WSH) 参数集合轻松地将清单 9 转换到命令行脚本。

接下来,这个脚本使用 VBScript 的 GetObject 函数连接到目标计算机上的 WMI 服务。注意传递到 GetObject 的连接字符串有什么不同?除了指定目标命名空间之外,类名也要进行指定,这对 GetObject 和 WMI 脚本库返回的内容有深远影响。如在我们前面的所有脚本,GetObject 返回一个对表示目标类的 SWbemObject 的引用,而不是返回对 SWbemServices 对象的引用。为什么?答案在于对象路径。虽然我们在第三部分中会详细讨论对象路径,但是这里我们还是给您一个概要的解释来帮助您理解清单 9 到清单 11(以及补充清单 C)中到底在进行些什么。

每个 WMI 类和每个 WMI 托管资源实例都有一个对象路径。将对象路径理解为一个文件的完全限定路径的 WMI 版本。每个文件都有一个完全限定路径,它由设备名称,后跟 0 或更多目录名称,再加上文件名组成。同样,每个类和托管资源也都有一个对象路径,它由启用了 WMI 的计算机名称,后跟 CIM 命名空间,后跟托管资源类名,后跟类的 key 属性以及 key 属性的值组成,如下所示。(注意,方括号只为了分清一个对象路径的四个许可部分,它们并不是对象路径的一部分。)

[//ComputerName][/Namespace][:ClassName][.KeyProperty='Value']

当您在传递到 GetObject 的连接字符串中使用全部或部分的对象路径时(顺便说一下,这就是我们一直在做的),您使用的对象路径确定了由 GetObject 和 WMI 脚本库返回的引用类型。例如,如果只包含了对象路径的计算机名称部分,您就会获得一个连接到默认命名空间的 SWbemServices 对象引用。如果包含了计算机名称和/或命名空间,您也会获得对 SWbemServices 对象的引用。如果包含了计算机名称、命名空间和类名,您将会获得对表示这个类的 SWbemObject 的引用。如果包含了所有四个部分,您将会获得表示由类、密钥和值识别的托管资源实例的 SWbemObject。再次提醒,我们会在本系列的第三部分更详细地讨论对象路径。现在,了解清单 9 中的 objClass 是对表示 Win32_Service 类的 SWbemObject 的引用。

脚本的剩余部分相当简明易懂。在回显一个简单的、标识其属性将被显示的类名的标题后,脚本使用从 GetObject 返回的 SWbemObject 引用 (objClass) 来访问 SWbemObjectProperties_ 属性 (objClass.Properties_)。SWbemObjectProperties_ 属性引用了一个 SWbemPropertySet,它是对这个类的属性的集合。SWbemPropertySet 集合中的每个属性都是一个 SWbemProperty (objClassProperty) 对象,我们用其读取并回显每个属性的名称。

概括地说,For Each 循环枚举了类的 SWbemPropertySet 集合(通过 SWbemObjectProperties_ 属性)并回显SWbemPropertySet 集合中每个 SWbemPropertyName 属性。

清单 9:使用 SWbemObject Properties_ 检索 Win32_Service 属性

strComputer = "."
strNameSpace = "root/cimv2"
strClass = "Win32_Service"

Set objClass = GetObject("winmgmts://" & strComputer & _
                         "/" & strNameSpace & ":" & strClass)

WScript.Echo strClass & " Class Properties"
WScript.Echo "------------------------------"

For Each objClassProperty In objClass.Properties_
    WScript.Echo objClassProperty.Name
Next

9 显示由 Win32_Service 类定义(或继承)的 25 个属性的名称。

scripting08132002_fig9

9GetProperties.vbs 输出

除了一个显著的例外,清单 10 与清单 9 是相同的。For Each 循环枚举类的 SWbemMethodSet 集合(通过 SWbemObjectMethods_ 属性),并回显 SWbemMethodSet 集合中每个 SWbemMethod (objClassMethod) 的 Name 属性。

清单 10:使用 SWbemObject Methods_ 检索 Win32_Service 方法

strComputer = "."
strNameSpace = "root/cimv2"
strClass = "Win32_Service"

Set objClass = GetObject("winmgmts://" & strComputer & _
                         "/" & strNameSpace & ":" & strClass)

WScript.Echo strClass & " Class Methods"
WScript.Echo "---------------------------"

For Each objClassMethod In objClass.Methods_
    WScript.Echo objClassMethod.Name
Next

10 显示由 Win32_Service 类定义(或继承)的 10 个方法的名称。

scripting08132002_fig10

10GetMethods.vbs 输出

除了三点例外,清单 11 与清单 9 和 清单10 相同。

1.

For Each 循环枚举类的 SWbemQualifierSet 集合(通过 SWbemObjectQualifiers_ 属性),并回显 SWbemQualifierSet 集合中每个 SWbemQualifier (objClassQualifier) 的 Name 属性。

2.

因为类限定符是类定义的一部分而且限定符有值,清单 11 也检索并回显 SWbemQualifierSet 集合中每个 SWbemQualifier (objClassQualifier) 的 Value 属性。

3.

因为一个限定符可以有多个存储在数组中的值,清单 11 必须在读取限定符的值前说明此点。如果不这么做,如果脚本试图将一个基于数组的限定符作为标量变量来读取,将会导致运行时错误。Win32_NTLogEvent 类的 Privileges 限定符是一个基于数组的限定符实例。

清单 11:使用 SWbemObject Qualifiers_ 检索 Win32_Service 类限定符

strComputer = "."
strNameSpace = "root/cimv2"
strClass = "Win32_Service"

Set objClass = GetObject("winmgmts://" & strComputer & _
                         "/" & strNameSpace & ":" & strClass)

WScript.Echo strClass & " Class Qualifiers"
WScript.Echo "------------------------------"

For Each objClassQualifier In objClass.Qualifiers_
    If VarType(objClassQualifier.Value) = (vbVariant + vbArray) Then
        strQualifier = objClassQualifier.Name & " = " & _
                       Join(objClassQualifier.Value, ",")
    Else
        strQualifier = objClassQualifier.Name & " = " & _
                       objClassQualifier.Value
    End If
    WScript.Echo strQualifier
    strQualifier = ""
Next

11 显示由 Win32_Service 类定义(或继承)的 5 个类限定符的名称和值。

scripting08132002_fig11

11GetClassQualifiers.vbs 输出

如您可能已经注意到的,清单 9 和清单 10 无法显示属性和方法限定符。说实话,这是故意让脚本保持在一个容易理解的大小。好消息是,在本专栏的结尾我们已经加入了完整的类限定符、属性、属性限定符、方法和方法限定符脚本(见补充清单 C)。欢迎参阅。

万一这不是很明显,您可以把清单 9、10、11 与清单 6(GetAllNamespaces.vbs 脚本)和清单 8(GetClasses.vbs 脚本)组合在一起来检索在 CIM 中定义的每个类的属性、方法和限定符。在使用所产生的带有 findstr.exe 命令的脚本,您会得到一个解决方案来搜索在 CIM 中定义的任何类、属性、方法或限定符。

使用 SWbemObject GetObjectText_

在前面我们说过,您可以直接从 MOF 文件(包含类的定义)中检索管理资源类定义。例如,如果您想要查找 Win32_Service 类,可以查看 %SystemRoot%/system32/wbem/cimwin32.mof 文件。但是,直接使用 MOF 文件是有代价的。您必须检查托管资源的类层次结构中的每个类,以获得完整的托管资源蓝图。

比如说,您想要查找 Win32_Service。您就不得不检查 Win32_Service 类层次结构中所有的 5 个类,以获得完整的蓝图,如图 1 所示,。如果您使用 WMI 测试器 (wbemtest.exe) 的 Show MOF 按钮(见图 7),也是同样。获得类的 MOF 表示形式的较简单方法是使用 WMI 脚本库的 SWbemObjectGetObjectText_ 方法,如清单 12 中演示的。

与清单 9 到 11 不同,清单 12 使用 SWbemServicesGet 方法来检索类,而不使用 GetObject。必须使用 SWbemServicesGet 方法,这样才能启用 wbemFlagUseAmendedQuailifiers 标志。启用 wbemFlagUseAmendedQuailifiers 标志,告诉 WMI 返回整个托管资源蓝图(类定义)而不仅仅是本地的定义。

使用 wbemFlagUseAmendedQualifiers 标记还有第二个好处。您也取回了类描述,以及对每个类的属性、方法和限定符的描述。类、属性、方法和限定符描述通常在一个本地化目的、单独的 MOF 文件中定义。例如,Win32_Service 类的中性语言部分是在 cimwin32.mof 中定义的。Win32_Service 类的特定语言部分,包括描述信息,是在 cimwin32.mfl 中定义的。特定语言的(或本地化的) MOF 文件通常带有一个 .mfl(而非 .mof)扩展名。

SWbemServicesGet 方法返回对表示目标类的 SWbemObject (objClass) 的引用,它用于调用 SWbemObjectGetObjectText_ 方法。GetObjectText_ 方法返回该类的 MOF 表示形式。如果我们使用了 GetObjectText_ 而没有启用 wbemFlagUseAmendedQuailifiers 标记,这个方法将只返回那些由 Win32_Service 定义的属性、方法和限定符,继承的属性和方法会被省略。

12:使用 SWbemObject GetObjectText_ 来检索 Win32_Service 类的 MOF 表现形式

strComputer = "."
strNameSpace = "root/cimv2"
strClass = "Win32_Service"

Const wbemFlagUseAmendedQualifiers = &h20000

Set objWMIService = GetObject("winmgmts://" & strComputer & "/" & strNameSpace)
Set objClass = objWMIService.Get(strClass, wbemFlagUseAmendedQualifiers)
strMOF = objClass.GetObjectText_

WScript.Echo strMOF

不过,对于使用 GetObjectText_ 有一个限定:没有关于在包含在由该方法返回的 MOF 语法中的继承限定符的信息。当 Key 限定符在一个父类的属性中定义时,如果您想要使用 GetObjectText_ 来确定一个类的 Key 属性,这可能会带来问题。

使用 SWbemObjectEx GetText_

Windows XP 和 Windows Server 2003 都包含一个名为 GetText_ 的新方法,它可以用于检索托管资源类定义的 XML 表现形式。

除了一个明显的例外,使用 GetText_ 与使用 GetObjectText_类似:传递到 GetText_ 方法的三个参数。

第一个参数是必需的,它标识所产生的 XML 格式。它目前可以是作为由 WMI WbemObjectTextFormatEnum 定义的两个值中的一个:wbemObjectTextFormatCIMDTD20(值:1)或 wbemObjectTextFormatWMIDTD20(值:2)。值 2 (wbemObjectTextFormatWMIDTD20) 告诉 GetText_ 根据 Distributed Management Task Force CIM 文档类型定义 (DTD) 2.0 版本的扩展 WMI 版本格式化所产生的 XML。

第二个参数是可选的,并且目前是为操作标记保留的。它必须被设置为 0(零)。

第三个参数 colNamedValueSet(也是可选的),是一个为 GetText_ 提供特殊说明的 SWbemNamedValueSet 集合。这里,我们让 GetText_ 进行:

检索并编码所有属性和方法,不仅仅是本地定义的属性和方法。

包含所产生的 XML 中的类限定符、属性限定符和方法限定符。

包含所产生的 XML 中的系统属性。

包含对所有属性和方法的类起源。

清单 13:使用 SWbemObjectEx GetText_ 来检索 Win32_Service 类的 XML 表现形式(仅限 Windows XP Windows .NET

strComputer = "."
strNameSpace = "root/cimv2"
strClass = "Win32_Service"

Const wbemFlagUseAmendedQualifiers = &h20000

Const wbemObjectTextFormatWMIDTD20 = 2

Set objWMIService = GetObject("winmgmts://" & strComputer & "/" & strNameSpace)
Set objClass = objWMIService.Get(strClass, wbemFlagUseAmendedQualifiers)

Set colNamedValueSet = CreateObject("Wbemscripting.SWbemNamedValueSet")
colNamedValueSet.Add "LocalOnly", False
colNamedValueSet.Add "IncludeQualifiers", True
colNamedValueSet.Add "ExcludeSystemProperties", False
colNamedValueSet.Add "IncludeClassOrigin", True

strXML = objClass.GetText_(wbemObjectTextFormatWMIDTD20, 0, colNamedValueSet)

WScript.Echo strXML

为了成功运行清单 13,将脚本复制并粘贴到您最常用的文本编辑器中,保存脚本(扩展名为 .vbs,例如:GetXML.vbs),然后使用下面列出的命令行运行脚本。

C:/Scripts> cscript //nologo GetXML.vbs >Win32_Service.xml

12 显示所生成的 XML 文件,Win32_Service.xml,使用 Microsoft Internet Explorer。

scripting08132002_fig12thumb

12GetXML.vbs 输出

就到这里吧

如果对 WMI 有任何疑惑、困难或不知所措,那可能是在处理由 WMI 公布的大量数据。我们愿意认为,我们已经为您装备了有效地寻找并解释 WMI 托管资源类定义所必需的知识和工具。当然,对于这一点您是最好的裁判,所以请尽量让我们知道我们是否以及有哪些不足。枯燥的内容结束了,准备在我们投入到 WMI 脚本库的详细信息时在第三部分玩得开心点吧。哦,不管怎么样,随意打发剩下的时间吧。

等一下!在您打包走人之前,还有最后一个要注意的地方:WMI 开发小组让我们告诉您,以前只能随 WMI SDK 使用的 WMI 工具,现在已经进行了更新。更新的工具(包括 WMI CIM Studio、WMI 事件注册、WMI 事件查看器 和 WMI 对象浏览器),现在都与 Windows XP 和 Windows Server 2003 以及 Windows 2000 兼容。此外,更新的工具不包含 WMI SDK,这意味着现在您可以安装这些工具而不必安装整个 WMI SDK。这难道不是非常酷么?

补充脚本

清单 A:列出在 root/cimv2 命名空间中定义的抽象类类型

strComputer = "."

Set objWMIService = GetObject("winmgmts://" & strComputer & "/root/cimv2")
Set colClasses = objWMIService.SubclassesOf()

For Each objClass in colClasses
    For Each objClassQualifier In objClass.Qualifiers_
        If LCase(objClassQualifier.Name) = "abstract" Then
            WScript.Echo objClass.Path_.Class   & ": " & _
                         objClassQualifier.Name & "="  & _
                         objClassQualifier.Value
        End If
    Next
Next
清单 B:列出在 root/cimv2 命名空间中定义的动态类类型
strComputer = "."

Set objWMIService = GetObject("winmgmts://" & strComputer & "/root/cimv2")
Set colClasses = objWMIService.SubclassesOf()

For Each objClass in colClasses
    For Each objClassQualifier In objClass.Qualifiers_
        If LCase(objClassQualifier.Name) = "dynamic" Then
            WScript.Echo objClass.Path_.Class   & ": " & _
                         objClassQualifier.Name & "="  & _
                         objClassQualifier.Value
        End If
    Next
Next

列表 C:使用 SWbemObject Qualifiers_Properties_ Methods_ 检索类限定符、属性、属性限定符、方法和方法限定符

strComputer = "."
strNameSpace = "root/cimv2"
strClass = "Win32_Service"

Set objClass = GetObject("winmgmts://" & strComputer & _
                         "/" & strNameSpace & ":" & strClass)

WScript.Echo strClass & " Class Qualifiers"
WScript.Echo "------------------------------"
i = 1
For Each objClassQualifier In objClass.Qualifiers_
    If VarType(objClassQualifier.Value) = (vbVariant + vbArray) Then
        strQualifier = i & ". " & objClassQualifier.Name & " = " & _
                                  Join(objClassQualifier.Value, ",")
    Else
        strQualifier = i & ". " & objClassQualifier.Name & " = " & _
                                  objClassQualifier.Value
    End If
    WScript.Echo strQualifier
    strQualifier = ""
    i = i + 1
Next

WScript.Echo
WScript.Echo strClass & " Class Properties and Property Qualifiers"
WScript.Echo "------------------------------------------------------"
i = 1 : j = 1
For Each objClassProperty In objClass.Properties_
    WScript.Echo i & ". " & objClassProperty.Name
    For Each objPropertyQualifier In objClassProperty.Qualifiers_
        If VarType(objPropertyQualifier.Value) = (vbVariant + vbArray) Then
            strQualifier = i & "." & j & ". " & _
                           objPropertyQualifier.Name & " = " & _
                           Join(objPropertyQualifier.Value, ",")
        Else
            strQualifier = i & "." & j & ". " & _
                           objPropertyQualifier.Name & " = " & _
                           objPropertyQualifier.Value
        End If
        WScript.Echo strQualifier
        strQualifier = ""
        j = j + 1
    Next
    WScript.Echo
    i = i + 1 : j = 1
Next

WScript.Echo
WScript.Echo strClass & " Class Methods and Method Qualifiers"
WScript.Echo "-------------------------------------------------"
i = 1 : j = 1
For Each objClassMethod In objClass.Methods_
    WScript.Echo i & ". " & objClassMethod.Name
    For Each objMethodQualifier In objClassMethod.Qualifiers_
        If VarType(objMethodQualifier.Value) = (vbVariant + vbArray) Then
            strQualifier = i & "." & j & ". " & _
                           objMethodQualifier.Name & " = " & _
                           Join(objMethodQualifier.Value, ",")
        Else
            strQualifier = i & "." & j & ". " & _
                           objMethodQualifier.Name & " = " & _
                           objMethodQualifier.Value
        End If
        WScript.Echo strQualifier
        strQualifier = ""
        j = j + 1
    Next
    WScript.Echo
    i = i + 1 : j = 1
Next

Scripting Clinic

Greg Stemp 长期以来被公认为美国国内的脚本编写权威之一,并且被大家广泛誉为世界级……哈哈!嗯,他们 的履历表中怎么都当过足球教练?真的吗?他被解雇 了?哦,好吧。Greg Stemp 工作在……哦,好了,难道我连这都不能说吗?好吧!Greg Stemp 从 Microsoft 领薪水,在那儿他拥有并不显赫的首席作家(System Administration Scripting Guide)的头衔。

Dean Tsaltas 是一个生活在 Redmond 的 Nova Scotian 人。他已经开始说一口流利的美语了,甚至会笑他的滨海省的朋友和家人们的发音。他的计算机生涯开始于他很小的时候,那时他的祖母和父母资助他,为他买了他心爱的 C-64,并为他订阅了 Compute! 的学报。现在,他已经在 Microsoft 工作了若干年,他有句话要告诉在家乡和温哥华的朋友和家人:“没有,我还没见过比尔!”

Bob Wells 漫无目的地四处游走,向每个听他说话的人大赞脚本编写的好处。有传言说,Bob 的两只达克思猎犬对脚本编写比大多数人类知道的都多。业余时间里,Bob 向 System Administration Scripting Guide 投稿。

Ethan Wilansky把他的很多的工作时间花在了写作和咨询方面。他狂热于脚本编写、瑜伽、园艺和他的家庭(不一定按此顺序)。他目前正致力于一种创建能倒垃圾和洗餐盘的脚本的方法。

 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

inject2006

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值