欢迎光临 Enjoy IT (ITECN.NET) 登录 | 注册 | 帮助

联合

公告

注意:本人的所有文档均可以引用,但引用必须说明出处。
跟我从头学WMI(三)--查询WMI

查询WMI

一.   枚举对象

WMI对象可以利用各种方法从公共信息模型(CIM)检索获取信息。

 

SWbemServices对象的GetObject函数和GET方法检索一个对象的单一实例。然而,同一类的多个对象往往组织成集合。所以

,不同的做法是从集合中浏览和检索对象。该方法是根据具体标准来枚举集合和访问感兴趣的对象。对象的标准是基于其

关键属性或属性。

SWbemServices.InstancesOf

一种枚举集合、检索特定对象的方法是使用SWbemServices对象的InstancesOf方法。获得了SWbemServices对象,您可以使

InstancesOf方法检索一个特定类的对象的集合。

比如,你想知道windows Installer安装的产品,下面的示例就显示了从win32_product对象的集合获得的信息:

For each Product in _

GetObject("WinMgmts:").InstancesOf("win32_product")

Wscript.Echo Product.name, " - ", Product.InstallState

Next

下面的例子检查特定的产品,Microsoft office 2000 Premium,如果找到,显示一个已经安装的信息。

Dim blnFound

blnFound = False

For each Product in

GetObject("WinMgmts:").InstancesOf("win32_product")

If Product.Name = "Microsoft Office 2000 Premium" Then

WScript.Echo "Office 2000 is installed"

blnFound = true

Exit For

End If

Next

If blnFound = False Then

WScript.Echo "Office 2000 is not installed"

End If

SWbemServices.ExecQuery

SWbemServices对象的ExecQuery方法是WMI管理脚本中最强大的方法 。它返回一个SWbemObject对象的集合,和

IntsancesOf方法相似。然而,ExecQuery方法使您可以指定一个独特的查询。你可以建立那些符合查询要求的对象的集合

。通常的语法如下:

objWbemObjectSet = objwbemServices.ExecQuery _

(strQuery,[strQueryLanguage="WQL"],

[iFlags=wbemFlagReturnImmediately],

[objWbemNamedValueSet=null]);

这语法中的描述由下表给出:

Argument                     Explanation

strQuery                     Required. String containing the text of the

                             query. This is the Select statement. This

                             parameter cannot be blank.

strQueryLanguage             Optional. String containing the query language

                             to be used. If specified, the value for this

                             parameter must be WQL. There are currently no

                             other query language options.

iFlags                       Optional. Integer that determines the behavior of

                             the query and whether this call returns

                             immediately. The default value for this

                             parameter is wbemFlagReturnImmediately

                             (value 16). The value of this parameter is used to

                             indicate amongst other things the synchronicity

                             of the operation.

objWbemNamedValueSet         Optional. Typically, this is undefined (null).

下面是一个使用ExecxQuery方法查询的实例

Set ObjSvc = GetObject("WinMgmts:")

Set objSet = objSvc.ExecQuery("Select * From Win32_Product")

For Each obj in objSet

WScript.Echo obj.name, obj.InstallState, obj.version

Next

WMI查询语法使得脚本针对CIM中的任何类使用复杂的查询语法。

当使用ExecQuery方法,你将接收到运行实时错误,下面的表描述最常见的run-time错误:

Error                    Return Code                Meaning

wbemErrAccessDenied      0x80041003                 Current user does not have permission

                                                    to view the result set.

wbemErrFailed            0x80041001                 Unspecified error.

wbemErrInvalidParameter  0x80041008                 Invalid parameter was specified.

wbemErrInvalidQuery      0x80041017                 Query syntax is not valid.

wbemErrInvalidQueryType  0x80041018                 Requested query language is not

                                                    supported.

wbemErrOutOfMemory       0x80041006                 Not enough memory to complete the

                                                    operation.

注意,返回一个空的集合不是一个错误,如果枚举一个空的集合,则是一个错误。比如,如果没有"Win32_Product"实例,一个空的SWbemObjectSet对象就被返回:

Set ObjSvc = GetObject("WinMgmts:")

Set objSet = objSvc.ExecQuery("Select * From Win32_Product")

如果你打算枚举这个集合,那么你就会得到一个错误:

For Each obj in objSet

WScript.Echo obj.name, obj.InstallState, obj.version

Next

你可以通过使用Count方法,看看在对象集中是否存在对象来避免错误:

Set ObjSvc = GetObject("WinMgmts:")

Set objSet = objSvc.ExecQuery("Select * From Win32_Product")

If objSet.count <> 0 Then

For Each obj in objSet

WScript.Echo obj.name, obj.InstallState, obj.version

Next

Else

Wscript.Echo “There were no products”

End If

ExecQuery方法不论是否在查询中是否需要关键属性,关键属性都会返回,比如,前面一个例子中,win32_product对象有三个关键属性,Name, IdentifyingNumberVersion,虽然在查询中只要NameInstallState属性,但Version属性也将被检索,因为它是关键属性。

 

二.   WMI查询语言

WMI查询语言(WQL)是基于American National Standards Institute (ANSI) SQL语句基础上的。

WQLWeb-based Enterprise Management(WBEM)查询语句的扩展。WMI查询语言包括一些额外的的语句,比如WITHIN

Associators Of,References Of.

当前,WQL仅仅用于检索数据,它不支持InsertUpdate,Delete,WQL支持下列三种类型查询:

×数据查询:

  数据查询用于检索类的实例和data associations

  SELECT * FROM Win32_Process

×事件查询

  Consumers use使用事件查询登记收到通知的事件。

  Event providers 使用事件查询登记,以支持一个或多个事件。

  SELECT * FROM __instanceCreationEvent

×架构查询

  架构查询被用于查询类的定义和架构组成。

  SELECT * FROM meta_class

  注意,架构查询已经超越了这门课的范围,如需要查询,请查阅SDK文档。

 

WQL的基本查询格式

Windows Management Service的查询服务处理WQL.

WQL查询包括以下的基本格式:

×一个select语句被用于指定什么属性将被检索

×from语句指定目标对象

×where语句过滤或限制结果

WQL不支持跨名称空间查询或associations。你不能将两个对象进行跨名称和集成的查询,但是,可以采用view provider来突破弥补这个限制。

 

三.   数据查询

数据查询

数据查询是需要类的实例的WQL语句。

下面是一个基本的select语句

SELECT * FROM Win32_LogicalDisk

这个语句返回指定类型和它的子类的实例,包含所有的系统和用户定义的这个类的属性。如果系统属性是不相关的特定查

询,系统属性包含空。

你可以通过指定特定属性来缩小查询范围:如下例

SELECT installDate, Manufacturer FROM Win32_Adapter

Where语句使得你可以过滤返回的数据,比如,如果你要列出每一个enabled的网卡的IP地址,可以使用下列脚本:

Set ObjSvc = GetObject("WinMgmts:")

Set ObjSet = objSvc.ExecQuery _

("Select IPAddress from Win32_NetworkAdapterConfiguration_

Where IPEnabled = TRUE")

For Each obj in objSet

If Not isNull(obj.IPAddress) Then

For i = Lbound(obj.IPAddress) to Ubound(obj.IPAddress)

Wscript.Echo obj.IpAddress(i)

Next

End If

Next

查询,默认情况下,返回所有指定类以及它的子类的所有实例,你可以使用__CLASS system属性来要求获得指定的类,排

除其子类,要做到这点,在where语句后面使用__CLASS system属性

SELECT * FROM CIM_MediaAccessDevice WHERE __CLASS =

’Win32_CDROMDrive’

注意,__class是由两个下划线开始的。

操作符

你可以使用ANSI SQL的草走符,比如=, <, >, <=, >=, IS, IS NOT <>,在数据查询中,WQL支持一个“更”操作符,

ISA

WQL里,ISIS NOT操作符仅可以用于Null

SELECT * FROM Win32_Fan WHERE Description IS Null

在数据查询的Where语句里使用isa操作符,可以要求在一个类的层次结构中的特定类型的嵌入对象。

同步

你可以使用ExecQueryAsync方法一部执行查询,它返回一个SWbemObject对象给SWbemSink对象,那个名称是作为参数传递

,通过触发OnObjectReady事件,SWbemSink对象然后一次返回集合里面的对象给调用的脚本。当在数据收集的时候,脚本

需要继续执行其他任务,通过采用ExecQueryAsync方法性能可以得到改善。

下面的示例采用异步ExecQueryAsync方法,计算在event logs中有多少个错误

Dim count: count = 0

Set objSvc = GetObject("WinMgmts:")

Set sink =

wscript.CreateObject("WbemScripting.SWbemSink","SINK_")

retVal = objSvc.ExecQueryAsync _

( sink,"Select * From Win32_ntLogEvent")

WScript.Echo "Don’t close this until the " & vbcrlf & _

"Asynchronous operation is done"

’We could continue with some other work here if required

Wscript.Quit

’-------- only subroutines below this line --------------

Sub SINK_OnCompleted(iHResult, objErrorObject,

objAsyncContext)

Wscript.echo "There were " & count & " error messages"

End Sub

Sub SINK_OnObjectReady(objObject, objAsyncContext)

If objObject.type = "error" Then

count = count + 1

End If

End Sub

It is simpler to execute your queries synchronously. This is much easier to

script and, for large enumerations, offers the best performance, as illustrated by

the following:

Set objSvc = GetObject("WinMgmts:")

Set objSet = objSvc.ExecQuery _

("Select * From Win32_ntLogEvent",,48)

For Each obj in objSet

If obj.type = "error" Then

count = count + 1

End If

Next

Wscript.Echo "There were " & count & " error messages"

 

四.   常见任务

使用通用查询脚本

大多数的管理任务可以使用相同的基本脚本来执行。

通用脚本

你可以使用Execquery方法来检索一个单一实例或一个实例集合,该Execquery方法比InstancesOf方法更有效,和

GetObjectGet方法一样有效。因此,它可以代替所有这些方法,并提供一个基本的脚本模板。

Set objSet = GetObject("WinMgmts:").ExecQuery _

("Select * from class where x=y")

For each obj in objSet

WScript.Echo obj.property

End If

Next

示例:

Set objSet = GetObject("WinMgmts:").ExecQuery _

("Select * from Win32_LogicalDisk where DeviceID = ’C:’")

For each obj in objSet

WScript.Echo "FreeSpace: " & obj.FreeSpace

Next

常见任务

作为一个管理员,你需要在远程服务器上找到当前哪些设置为自动启动的服务是停止的:

Set objSet = GetObject("WinMgmts:\\Server1").ExecQuery _

("Select * from Win32_Service where State=’Stopped’_

and StartMode=’Auto’")

For each obj in objSet

WScript.Echo obj.Description

Next

在发现了多个有问题的服务后,你决定最好的方法是重新启动服务,在做这个之前,你想备份应用程序日志后清除它,你

必须有backup的特权才能执行这个动作,下面的实例使用backup特权并且清除应用程序日志:

Set objSet =

GetObject("WinMgmts:{(Backup)}\\Server1").ExecQuery _

("Select * from Win32_NTEventLogFile Where _

LogFileName=’Application’")

For each obj in objSet

RetVal = obj.BackupEventlog("c:\BACKUP.LOG")

if RetVal = 0 then WScript.Echo "Log Backed Up"

RetVal = obj.ClearEventlog()

if RetVal = 0 then WScript.Echo "Log Cleared"

Next

现在,你可以重新启动目标计算机,为了加快重新启动的速度,你可以减少重新启动延时

Set objSet = GetObject("WinMgmts:\\Server1").ExecQuery _

("Select * from Win32_ComputerSystem")

For each obj in objSet

obj.systemStartupDelay = 2

obj.put_

Next

下一步,你把自己赋予RemoteShutdown特权,并且重新启动计算机:

Set objSet =

GetObject("WinMgmts:{(RemoteShutdown)}\\Server1").ExecQuery _

("Select * from Win32_OperatingSystem Where Primary=True")

For each obj in objSet

obj.Reboot()

Next

 

五.   Associations and References

1.       Associations

一个Association是一个类,它包含两个或更多References,它代表了两个或更多个对象之间的关系,每一个association的实例代表了两个特定的WMI对象之间的关系。

类的类型

一个Association是一个类,您可以建立一个类之间的关系,而不影响任何有关的类,重要的是一个association类可以看作表达关系,比如,网卡和网络协议,一张网卡可以有很多协议,而协议可以绑定在多张网卡上,要定义这种关系,WMI使用一个中介类,叫做Win32_ProtocolBinding,这个类只有一个属性涉及到网卡和协议。

通常,association类没有任何相关之外的非系统属性,但是,有一些例外,为方便起见,Win32_LogicalFileAccessWin32_LogicalShareAccess 这些association类也包含AccessMask属性。

命名

依照常规,一个association对象将使用相关的来年改革对象来命名,下面是一些示例:

Association class                References

Win32_LogicalShareAccess         Links a share with security settings

Win32_LogicalFileAccess          Links a file with security settings

Win32_ProtocolBinding            Links a protocol, a driver, and an adapter

 

2.       查询Associations

查询Associations

一个WQL查询的特殊变化,可以被用于发现或枚举特定对象的associations

你可以使用Associators Of语句来查找所有关联对象的Association对象。通过查找中介Association对象。你可以枚举所

在信任关系中的所有对象,被称为endpoint对象。

下面的示例显示如何使用Associators Of语句,

(查找通过Win32_NetworkAdapter类的第一个Associations实例所关联的所有的对象)

Set objService = getObject("WinMgmts:")

Set assocSet = objService.ExecQuery _

("Associators Of {win32_networkAdapter.deviceID=’0’}")

For Each assoc in assocSet

strAssoc = strAssoc & assoc.Path_.RelPath & vbcrlf

Next

MsgBox strAssoc,vbInformation,"Associations of " & _

" Win32_networkAdapter"

下面这个实例列出所有的对象,这个对象关联一个特定的共享名称Temp

Set objService = GetObject("WinMgmts:")

Set assocSet = objService.ExecQuery _

("Associators Of {win32_share.name=’Temp’}")

For Each assoc in AssocSet

strAssoc = strAssoc & assoc.Path_.RelPath & vbcrlf

Next

MsgBox strAssoc,vbInformation,"Associations of " & " _

Win32_Share"

注意,当值存储在WMI中的时候,它使用(\)来作为一个escape字符,所以,'‘c:\temp’'被写为' ‘C:\\temp'

通过使用Where语句,你可以优化或过滤从endpoint对象返回的集合,但是,这和在select语句中的where语句不同,在Associators Of语句中,Where语句过滤器限于下列语法:

Associators Of {ObjectPath} WHERE

AssocClass = AssocClassName

ClassDefsOnly

RequiredAssocQualifier = QualifierName

RequiredQualifier = QualifierName

ResultClass = ClassName

ResultRole = PropertyName

Role = PropertyName

比如,仅返回Win32_LogicalShareSecuritySetting association 类的endpoint对象的Temp共享:

Set assocSet = objService.ExecQuery _

("Associators Of {win32_share.name=’Temp’} WHERE _

ResultClass=Win32_LogicalShareSecuritySetting")

3.查询References

         References Of语句和Associators Of语句一样,但不返回endpoint对象,它枚举Association对象自己

下面是References Of语句语法

References Of {SourceObject} WHERE

ClassDefsOnly

RequiredQualifier = QualifierName

ResultClass = ClassName

Role = PropertyName

比如,要看用自己相关的endpoint对象,链接到Temp共享的association对象,可以用下边的代码:

Set objService = getObject("WinMgmts:")

Set assocSet = objService.ExecQuery _

("References Of {win32_share.name=’temp’}")

For Each assoc in AssocSet

strAssoc = strAssoc & assoc.Path_.RelPath & vbcrlf

Next

MsgBox strAssoc,vbInformation,"References Of " & "_

Win32_Share"

 

六. 优化查询

对于大多数的脚本用于普通管理员的任务,性能问题可以忽略不计。但如果脚本要返回大量的数据,或通过网络传送,那么优化提高性能是有意义的。

 ExecQuery vs. InstancesOf

通常采用SWbemServices.ExecQuery方法要在性能上好于SWbemServices.InstancesOf方法。

限制需要的属性数量

只检索需要的的属性将减少需要返回的数量,减少了数据返回量,查询就能执行得更快。

这不仅在本地有效,在远程查询中也是如此,因为带宽是一个要考虑的因素。同事,某些属性比其他属性更容易被检索,

即使在同一个对象中,比如,检索磁盘的名称就比检索磁盘的剩余空间快很多。因为后者需要扫描驱动程序。

使用Where减少返回的对象数量

采用where语句可以明显的改善查询性能,另外优点是,当枚举查询结果时,不再需要测试每个项目是否是需要的结果。

举例:

Set objSvc = GetObject("WinMgmts:")

Set objSet = objsvc.ExecQuery("Select FreeSpace from

Win32_LogicalDisk")

For Each obj in objSet

If obj.deviceID = "C:" Then

wscript.echo obj.freespace

End If

Next

Set objSvc = GetObject("WinMgmts:")

Set objSet = objsvc.ExecQuery("Select FreeSpace from

Win32_LogicalDisk Where DeviceID = ’C:’")

For Each obj in objSet

wscript.echo obj.freespace

Next

Providers

ExecQuery方法实际执行情况依赖于被用于连接Provider

WMI具有后过滤功能,因此,如果返回结构超出了where语句的定义,它仍旧能在这个阶段消除那些需要过滤的数据,Provider利用这一功能,如果(where语句)提出请求的查询太复杂,则采用这个功能,但对于“复杂”的定义,是由provider来决定的,每个provider可能不同,因此,如果语句中存在着provider无法处理的的where语句,就有更多的对象返回,这些需要在随后的WMI筛选中处理,这样,性能将步入好的查询。

多数provider在关键属性上做了查询优化,下面是示例:

ResultSet = objService.ExecQuery _

("Select Name, ProcessID from win32_Service _

Where Name = ’Alerter’")

下面是一些优化的对比示例:

Query statement                         Optimization

Select * from Win32_LogicalDisk         No optimization is possible.

Select name from Win32_LogicalDisk      The Name property is available in the

                                        operating system, so this is easy to fetch.

                                        The disk does not need to be scanned.

Select name, freespace from _            All the disks have to be scanned,

Win32_LogicalDisk                        including the floppy disk drive, so this is slow.

                                        

Select name, freespace from _           This is better, because only one disk is scanned.

Win32_LogicalDisk _

where deviceID = ‘C:’

Select * from Win32_LogicalDisk _       The query service realizes it can identify

 where deviceID = ‘C:’                    this object by its key property and

                                        performs a GetObject to fetch it, rather

                                        than a query. The GetObject method

                                        retrieves an instance with all its properties

                                        and is much faster.

 

. View Provider

你可以使用view Provider来创建基于其他类的实例的新类。这些类作为view class像关联,并且类似于关系型数据库视图。

你可以使用view Provider来创建基于其他类的实例的新类。这些类作为view class像关联,并且类似于关系型数据库视图。

view class的原类可以是相同或不同的的名称空间,通过使用View Provider,你可以创建view class

view class

三种类型的view class

! Join View classes

! Union View classes

! Association View classes

MOF Syntax for a Join View

[JoinOn

(

"Win32_NetworkAdapter.MACAddress = _

Win32_NetworkAdapterConfiguration.MACAddress"

),

ViewSources

{

"SELECT MACAddress,TimeOfLastReset FROM _

Win32_NetworkAdapter",

"SELECT MACAddress, DHCPEnabled,DHCPLeaseExpires FROM _

Win32_NetworkAdapterConfiguration"

},

ViewSpaces

{

"\\\\Server1\\root\\cimv2::\\\\Server2\\root\\cimv2",

"\\\\Server1\\root\\cimv2::\\\\Server2\\root\\cimv2"

},

dynamic: ToInstance, provider("MS_VIEW_INSTANCE_PROVIDER")]

class JoinedAdapterConfig

{

[PropertySources{"MACAddress","MACAddress"},key] String MAC;

[PropertySources{"TimeOfLastReset",""}] DateTime LastReset;

[PropertySources{"","DHCPEnabled"}] Boolean DHCPOn;

[PropertySources{"","DHCPLeaseExpires"}] DateTime _

DHCPExpires;

};

Example

Delivery Tip

Point out the different

sections of the MOF file and

their purpose. This will be

important in subsequent

labs.

 

 

已发表 2009年4月8日 12:46 作者 qiqinghua

评论

尚无任何评论

禁止匿名发表评论