使用脚本程序管理Windows网络 第三部分:理解WMI

日期:2008-9-26作者:Mitch Tulloch

【TechTarget中国原创】了解Windows Management Instrumentation(WMI)是如何工作,以及如何使用VBScript脚本,本文最初发表于windowsnetworking.com。

  在本系列专题的前两篇文章中,我们了解到如何使用VBScript修改一个Windows计算机的一个网络适配器的IP地址。其中,我们还学到了很多关于Windows脚本编写的基本概念,如类、对象、属性、方法和不同类型的变量,包括字符串变量、整数变量、数组和集合。我们还了解到一些关于写好脚本的基本方法,如定义变量、实现错误处理、接受用户设置、显示验证输出,以及通过注释来文档化脚本。

我们一直都在努力坚持原创.......请不要一声不吭,就悄悄拿走。

我原创,你原创,我们的内容世界才会更加精彩!

【所有原创内容版权均属TechTarget,欢迎大家转发分享。但未经授权,严禁任何媒体(平面媒体、网络媒体、自媒体等)以及微信公众号复制、转载、摘编或以其他方式进行使用。】

微信公众号

TechTarget微信公众号二维码

TechTarget

官方微博

TechTarget中国官方微博二维码

TechTarget中国

作者>更多

Mitch Tulloch
Mitch Tulloch

Mitch Tulloch是一个作家、培训师和Windows服务器操作系统、IIS管理、网络故障修复和安全方面的专业顾问。他已经写了15本书,其中包括:Microsoft Encyclopedia of Networking (Microsoft Press),Microsoft Encyclopedia of Security (Microsoft Press),Windows Server Hacks (O'Reilly),Windows Server 2003 in a Nutshell (O'Reilly),Windows 2000 Administration in a Nutshell (O'Reilly),and IIS 6 Administration (Osborne/McGraw-Hill)。Mitch居住在加拿大的Winnipeg,你可以他的网站www.mtit.com查到更多关于他的书的信息。

网络性能管理>更多

相关推荐

技术手册>更多

  • 广域网控制终极指南

    如今,企业对广域网的依赖性越来越强了,对于地理位置分散的网络来说其需求更是空前的。本技术手册将会介绍促使广域网发展的重要原因,以及企业可以部署实施哪些策略和技术,来管理流量,提高性能并且控制成本,还介绍了通过自己内部部署广域网优化和通过广域网服务提供商部署广域网优化的利弊之处。

  • 网管员必读系列——用户管理指南

    管理员的职责是最大化系统的可用性和实用性,同时满足每个用户对“安全”的信息和通信环境的合理期望。用户管理至关重要。

  • VPN安全指导手册

    VPN(Virtual Private Network),即“虚拟专用网络”,是对企业内部网的扩展。虚拟专用网可以帮助远程用户、公司分支机构、商业伙伴及供应商同公司的内部网建立可信的安全连接,并保证数据的安全传输。

  • 防火墙应用指导手册

    防火墙是为防止非法访问或保护专用网络而设计的一种系统。本文将从防火墙的简介、种类、选择的方法、配置、管理和维护等几个方面向您做详细的讲解。

TechTarget

最新资源
  • 安全
  • 存储
  • CIO
  • 虚拟化
  • 服务器
  • 数据中心
【TechTarget中国原创】

了解Windows Management Instrumentation(WMI)是如何工作,以及如何使用VBScript脚本,本文最初发表于windowsnetworking.com。

在本系列专题的前两篇文章中,我们了解到如何使用VBScript修改一个Windows计算机的一个网络适配器的IP地址。其中,我们还学到了很多关于Windows脚本编写的基本概念,如类、对象、属性、方法和不同类型的变量,包括字符串变量、整数变量、数组和集合。我们还了解到一些关于写好脚本的基本方法,如定义变量、实现错误处理、接受用户设置、显示验证输出,以及通过注释来文档化脚本。

我们的最终脚本已经按要求工作了,但可能仍有一些方面你觉得难以理解。比如,让我们看一下下面这一行:

Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")

在我的第一篇文章,对于这一行我作了以下评论:“通过定义一个objWMIService对象并将它赋值为GetObject方法返回的句柄,就可以连接到本地计算机的root\cimv2命名空间了”。

这究竟意味着什么呢?到底什么是WMI,它究竟是如何工作的呢?而且为什么它对于想要了解如何编写脚本来管理Windows电脑的你来说是如此重要的呢?

理解WMI

大约在Window98出现或是更早以前,WMI就已经出现,只是这那之前它有一个不大相同的名称:基于Web的企业管理(WBEM) 。 WBEM是由Microsoft,Cisco,Intel,Compaq和BMC Software共同开发的技术,目的是为是更容易管理企业环境中的桌面系统和服务器系统。WMI提供了一个模型以表示、存储和查询Windows计算机的配置和状态信息以及其他运行状况。开发人员可以使用WMI写脚本或托管的代码去查看和修改设置在Windows电脑上的配置,以此查看Windows的应用和服务的状态,同时还做了很多其他有助于管理员进行Windows网络部署、维护和故障排除的其他的功能。

换句话说, WMI表示:

有一个很好的比喻是把Windows电脑比一个汽车,而WMI则作为你车上的控制台的电子(仪表),以显示上你车子的速度、引擎温度、RPMS 等等。这些仪表板的控制并不是它们自身完成的——你仍然要想出办法通过获取这些电子信息并且以一个可读的形式显示出来。使用WMI写VBScripts就是如同创造仪表板显示元件一样,整合到汽车的仪表盘中,以告诉你所想知道的信息并控制你的引擎。换句话说,Windows安装了通过WMI构建的所有这些工具——你只需要弄清楚如何使用它就可以通过它做一些有用的事情,比如改变你机器的IP地址、查看当前的时区、重启远程机器、显示已安装的修复程序列表等等。

WMI命名空间

我们要了解关于MWI的所有事,现在还不够。实际上,要找出WMI是否可以做一些特别的事情是需要一点耐心和领会能力的。让我们首先考虑WMI命名空间。在WMI术语,一个名字空间是类和类的实例的一种逻辑数据库。下面是一个简单的shownamespaces.vbs脚本,它列举了在根命名空间下的所有WMI命名空间:

Set objWMIService = GetObject("winmgmts:\\.\root")
Set colNamespaces = objWMIService.InstancesOf("__NAMESPACE")
For Each objNamespace In colNamespaces
     WScript.Echo objNamespace.Name
Next

下面是在WindowsXP 机器上运行这个脚本的结果:

C:\scripts>cscript ShowNamespaces.vbs
Microsoft (R) Windows Script Host Version 5.6
Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.
SECURITY
RSOP
Cli
SecurityCenter
WMI
CIMV2
Policy
Microsoft
DEFAULT
directory
subscription

每个这样的命名空间都是一个可能的来源,你可以查询关于Window计算机某个状态或配置的资料(而且也可以经常修改配置)。这些命名空间是像硬盘驱动器上的文件夹分层次地组织的。例如,我们可以通过下面的方式修改我们脚本的第一行来显示在root\CIMN2命名空间下的所有的命名空间:

Set objWMIService = GetObject("winmgmts:\\.\root\CIMV2")

当你运行修改后脚本时,输出结果是这样的:

C:\scripts>cscript ShowNamespaces.vbs
Microsoft (R) Windows Script Host Version 5.6
Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.
ms_409
Applications

事实上,root\ CIMV2是Windows机器上默认的WMI命名空间。这意味着,如果你在脚本的第一行里不指定连接的命名空间,那么WMI默认就会自动连接到root\ CIMV2命名空间。因此,如果我们将第一行改为:Set objWMIService = GetObject("winmgmts:\\") ... 我们会得到与上面相同的结果。请注意,我们去掉了winmgmts:\\.\\root\CIMV2句号后面的内容。如果你还记得在我们的第一篇文章,这个句号表示本地计算机,同时默认地WMI假设你想要在本地计算机上工作,这意味着你可以去掉句号后面的部分。而编写脚本最好的做法是在脚本中使用变量(来定义它们),以下是一个更广泛使用的可以用来显示WMI命名空间脚本:

Option Explicit
On Error Resume Next
Dim strComputer
Dim strWMINamespace
Dim objWMIService
Dim colNamespaces
Dim objNamespace
strComputer = "."
strWMINamespace = "\root\CIMV2"
Set objWMIService = GetObject("winmgmts:\\" & strComputer & strWMINamespace)
Set colNamespaces = objWMIService.InstancesOf("__NAMESPACE")
For Each objNamespace In colNamespaces
     WScript.Echo objNamespace.Name
Next

为什么要把它变得这么复杂呢?主要的原因是增加灵活性!举例来说,如果我们需要运行在远程计算机上运行这个脚本,我们可以改变strComputer为远程计算机的IP地址值。或者如果我们需要显示命名空间的不同部分,我们可以添加几行到我们的脚本中以接受用户对strWMINamespace变量的输入。

WMI提供者

找到合适的命名空间只是第一个挑战(虽然大部分的情况下连接到默认的命名空间就已经足够了)。你还必须访问正确的提供者,以便取回或更新你的目标系统的数据。下面是一个ShowProviders.vbs脚本,可以显示root\CIMV2命名空间的所有WMI提供者:

Option Explicit
On Error Resume Next
Dim strComputer
Dim strWMINamespace
Dim objWMIService
Dim colWin32Providers
Dim objWin32Provider
strComputer = "."
strWMINamespace = "\root\CIMV2"
Set objWMIService = GetObject("winmgmts:\\" & strComputer & strWMINamespace)
Set colWin32Providers = objWMIService.InstancesOf("__Win32Provider")
For Each objWin32Provider In colWin32Providers
     WScript.Echo objWin32Provider.Name
Next

以下就是在Windows XP机器上运行这个脚本的输出结果:

C:\scripts>cscript ShowProviders.vbs
Microsoft (R) Windows Script Host Version 5.6
Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.
Win32_WIN32_TSLOGONSETTING_Prov
MS_NT_EVENTLOG_PROVIDER
Win32_WIN32_TSENVIRONMENTSETTING_Prov
SCM Event Provider
ProviderSubSystem
VolumeChangeEvents
NamedJobObjectLimitSettingProv
HiPerfCooker_v1
WMIPingProvider
Microsoft WMI Forwarding Event Provider
Win32_WIN32_TSNETWORKADAPTERSETTING_Prov
SystemConfigurationChangeEvents
Win32_WIN32_TERMINALSERVICE_Prov
Win32_WIN32_TSREMOTECONTROLSETTING_Prov
Win32_WIN32_TSNETWORKADAPTERLISTSETTING_Prov
Win32_WIN32_COMPUTERSYSTEMWINDOWSPRODUCTACTIVATIONSETTING_Prov
Win32_WIN32_TSSESSIONDIRECTORY_Prov
CmdTriggerConsumer
Standard Non-COM Event Provider
SessionProvider
WBEMCORE
RouteEventProvider
WhqlProvider
Win32_WIN32_TSSESSIONSETTING_Prov
Win32_WIN32_TERMINalterMINALSETTING_Prov
Win32_WIN32_TSCLIENTSETTING_Prov
Win32_WIN32_TERMINALSERVICESETTING_Prov
WMI Kernel Trace Event Provider
Win32_WIN32_PROXY_Prov
NamedJobObjectProv
MS_Shutdown_Event_Provider
SECRCW32
Win32ClockProvider
MS_Power_Management_Event_Provider
Win32_WIN32_WINDOWSPRODUCTACTIVATION_Prov
RouteProvider
Cimwin32A
Msft_ProviderSubSystem
Win32_WIN32_TERMINALSERVICETOSETTING_Prov
NamedJobObjectSecLimitSettingProv
Win32_WIN32_TSSESSIONDIRECTORYSETTING_Prov
Win32_WIN32_TSPERMISSIONSSETTING_Prov
Win32_WIN32_TSACcount_Prov
Win32_WIN32_TERMINAL_Prov
MSIProv
DskQuotaProvider
NetDiagProv
Win32_WIN32_TSGENERALSETTING_Prov
CIMWin32
NamedJobObjectActgInfoProv
NT5_GenericPerfProvider_V1
WMI Self-Instrumentation Event Provider
MS_NT_EVENTLOG_EVENT_PROVIDER

看起来很复杂,不是吗?但是,使用这一系列的提供者,你可以轻松地搜索MSDN上有关某一特定提供者的更多的信息,并找到它所支持的方法。这就是你可以使用WMI对供应商所做的操作。

WMI类

除了命名空间和提供者,如果你想要利用WMI来脚本化Windows管理任务,你还需要理解WMI类。一个类是你可以用WMI管理的一种类型对象的一种模板。比如,Win32_LogicalDisk类是一个Windows机器上的逻辑磁盘摸板,而WMI则使用这个类为每一个安装的硬盘产生一个实例。

下面的ShowClasses.vbs脚本显示root\CIMV2命名空间的所有类(潜在的管理对象):

Option Explicit
On Error Resume Next
Dim strComputer
Dim strWMINamespace
Dim objWMIService
Dim colClasses
Dim objClass
strComputer = "."
strWMINamespace = "\root\CIMV2"
Set objWMIService = GetObject("winmgmts:\\" & strComputer & strWMINamespace)
Set colClasses = objWMIService.SubclassesOf()
For Each objClass In colClasses
    WScript.Echo objClass.Path_.Path
Next

下面是在Windows XP上运行这个脚本时输出的内容:

C:\scripts>cscript ShowClasses.vbs
Microsoft (R) Windows Script Host Version 5.6
Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.
\\XP\ROOT\CIMV2:__SystemClass
\\XP\ROOT\CIMV2:__thisNAMESPACE
\\XP\ROOT\CIMV2:__Provider
\\XP\ROOT\CIMV2:__Win32Provider
\\XP\ROOT\CIMV2:__IndicationRelated
\\XP\ROOT\CIMV2:__EventGenerator
\\XP\ROOT\CIMV2:__TimerInstruction
\\XP\ROOT\CIMV2:__IntervalTimerInstruction
...
\\XP\ROOT\CIMV2:MSFT_WMI_GenericNonCOMEvent
\\XP\ROOT\CIMV2:MSFT_WmiSelfEvent
\\XP\ROOT\CIMV2:Msft_WmiProvider_OperationEvent
\\XP\ROOT\CIMV2:Msft_WmiProvider_ComServerLoadOperationEvent
\\XP\ROOT\CIMV2:Msft_WmiProvider_InitializationOperationFailureEvent
\\XP\ROOT\CIMV2:Msft_WmiProvider_LoadOperationEvent
\\XP\ROOT\CIMV2:Msft_WmiProvider_OperationEvent_Pre
\\XP\ROOT\CIMV2:Msft_WmiProvider_deleteClassAsyncEvent_Pre
\\XP\ROOT\CIMV2:Msft_WmiProvider_GetObjectAsyncEvent_Pre
...
\\XP\ROOT\CIMV2:Win32_ComputerSystemEvent
\\XP\ROOT\CIMV2:Win32_ComputerShutdownEvent
\\XP\ROOT\CIMV2:Win32_SystemTrace
\\XP\ROOT\CIMV2:Win32_ModuleTrace
\\XP\ROOT\CIMV2:Win32_ModuleLoadTrace
\\XP\ROOT\CIMV2:Win32_ThreadTrace
\\XP\ROOT\CIMV2:Win32_ThreadStartTrace
\\XP\ROOT\CIMV2:Win32_ThreadStopTrace
\\XP\ROOT\CIMV2:Win32_ProcessTrace
\\XP\ROOT\CIMV2:Win32_ProcessStartTrace
\\XP\ROOT\CIMV2:Win32_ProcessStopTrace

同样,这一切看起来有点还是挺复杂的,但你可以使用这些类在MSDN上搜索更多关于某一特定的WMI类信息,以此找到这个类相关的属性和方法。

使用WMI

下面让我们学以致用。上面脚本中显示的其中一个类是Win32_TimeZone,让我们用这个类显示电脑上所配置的时区。首先,我们需要知道关于这个类的更多信息,在MSDN上搜索“Win32_TimeZone类”会找到关于它的信息网页。在这个页面中我们可以找到这个类所支持的属性和方法(虽然实际上这个特定的级别只有属性而没有方法),这样使用这些信息,我们就应该可以写出我们所要的脚本。

这个小实验证明Caption属性是我们所要显示的,因为这是存储在机器上对最可读的(human-readable)形式的时区信息。以下这个命名为DisplayTimeZone.vbs的脚本,我们将用其查询WMI ,搜索这方面的资料并进行显示:

Option Explicit
On Error Resume Next
Dim strComputer
Dim strWMINamespace
Dim strWMIQuery
Dim objWMIService
Dim colItems
Dim objItem
strComputer = "."
strWMINamespace = "\root\CIMV2"
strWMIQuery = "select   FROM Win32_TimeZone"
Set objWMIService = GetObject("winmgmts:\\" & strComputer & strWMINamespace)
Set colItems = objWMIService.execQuery(strWMIQuery)
For Each objItem In colItems
    WScript.Echo objItem.Caption
Next

这就是运行脚本所显示的结果:

C:\scripts>cscript DisplayTimeZone.vbs
Microsoft (R) Windows Script Host Version 5.6
Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.
(GMT-06:00) Central Time (US & Canada)

让我们看看这个脚本是如何工作的。首先,你可以看到它很多基于我们先前的脚本。换句话说,我们是从使用以下语句连接WMI开始的:

Set objWMIService = GetObject("winmgmts:\\" & strComputer & strWMINamespace)

而下面一句是新的:

Set colItems = objWMIService.execQuery(strWMIQuery)

我们在这里要做的是执行对WMI一个查询以从中收集一些信息。这个查询已经在之前使用以下的语句定义了:

strWMIQuery = "select  FROM Win32_TimeZone"

这个SQL的select语句本质上返回Win32_TimeZone提供者所能提供给我的所有记录(*号),然后将这些结果保存在colItems集合中。然后,我们循环遍历集合中的每一项(其实查询结果中只有一项记录)和显示这一项的Caption属性,就是下列字符串:

(GMT-06:00) Central Time (US & Canada)

练习

我们将在这一系列接下来的文章中深入研究WMI脚本编写,但现在让我们尝试做一个练习。将上面displaytimezone.vbs脚本中的内容到记事本(保证自动换行是关闭的),并将其另存为PageFile.vbs。现在修改脚本上的一行(实际上只是一行的一小部分),这样当脚本运行时显示路径和系统的PageFile(也就是虚拟内存)而不是时区。提示:在MSDN上搜索有关Win32_PageFile类的信息。我将在接下来的系列文章中解释这个练习的答案。