WMI对象
一. 使用脚本连接到WMI
1. 使用SWBEM脚本API
SWBEM脚本是可以用来访问和控制WMI内部对象的一系列可用在脚本中的对象。
Scripting object model
脚本通过访问wbemdisp.dll这个library来访问wmi对象,这个仅被设计用来为脚本工作。
Collections
Swbem API支持collection object。这些对象包含其它对象,比如用脚本返回系统正在运行的进程,那么返回的就是一个collection,包含很多对象,每个对象包含一个单独的进程
For Each objProc in objProcSet
WScript.Echo objProc.name
Next
属性和方法
对象包含属性和方法,在脚本中,在名称后用点来分隔,比如:objProc.name.
属性数组
有些wmi的属性是一个数组,比如在Win32_NetworkAdapterConfiguration的WMI类中,IPAddress属性就是一个数组
你用下面的脚本就会报错:
WScript.Echo NicConfig.IPAddress
必须用下面的脚本来反映可能的组件构成
If isArray(obj.IPAddress) Then
For i = 0 to Ubound(obj.IPAddress,1)
strResult = strResult & " IP: " _
& obj.Ipaddress(i) & vbcrlf
Next
Else
strResult = strResult & obj.IPAddress & vbcrlf
End If
Wscript.Echo strResult
2.使用一个locator获得WMI的连接
有两种方法可以通过脚本连接到WMI
第一种是locator对象
你可以通过vbs编辑器直接创建locator对象,SWbemLocator对象是对象模式中可以通过vbscrip来创建的对象模型之一,创建这个对象的实例.
vbscrip来创建的对象模型之一,创建这个对象的实例,
Set objLocator = _
CreateObject("wbemScripting.SwbemLocator")
ConnectServer方法被用来为特定服务器和名称空间提交一个SWbemServices对象,在这个过程中要提交相应的安全信息
Set object = LocatorObjects.ConnectServer _
(ServerName, Namespace, UserAccount, UserPassword,_
Locale, Authority, SecurityFlags, NamedValueSet)
Enumerate (例举、枚举对象)
返回:属性,方法
3.使用Moniker获得WMI的连接
什么是Moniker(绰号)
Moniker是COM程序的概念,简单讲,就是用来替代掉复杂的在COM下的链接对象。
在脚本中,你可以通过显示名称来使用Moniker的,比如WinMgmts
WMI使用WinMgmts:前缀
WinMgmts:是一个反应地点和验证绑定的WMI名称空间的moniker。
于此类似的是adsi,用来连接到不同的目录服务。
它使用VBScript的GetObject方法
下面是举例:
Set objSvc = GetObject("WinMgmts:")
对于moniker,在语法上有明显的三部分:强制部分,安全部分,对象路径
Mandatory Component(强制组件)
至少,moniker语法包含winmgmts:上面的例子显示了moniker如何使用仅有的一个强制组件,它返回一个SWbemservice对象,链接到本地计算机和默认的名称空间root\cimv2上,使用的票证是当前的登录用户
Security Setting components
安全设置选项是一个可选项,默认的默认的安全设置对于大多数的WMI脚本是足够的,
! Impersonation
! Authentication
! Authority
! Privileges
设置在括号中,如下列示例:
Set objSvc = _
GetObject("WinMgmts:{impersonationLevel=impersonate}")
local setting component
允许脚本制定语言版本,比如对象描述是一个字符串,CIM存有不同语言版本的字符串,local setting允许脚本决定采用什么样的版本
Set objSvc = _ GetObject("WinMgmts:[Locale = ms_409]")
这个例子,代表着使用Language ID x409的语言,指的是US English
WMI Object Path Component
在WinMgmts,可以使用下列的参数,来对一个对象进行描述
! The server.
! The namespace.(比如从默认的root\cimv2变为root\snmp)
! The object.
这意味着使用winmgmts:moniker语法可以连接到远程计算机上。
越来越多的应用程序使用自己的独立的名称空间,比如root\MicrosoftSQLServer名称空间用于SQLServeradmin provider,用于通过WMI管理SQL server.
举例:下面是在默认的root\cimv2名称空间,这三部分可以多样的组织,这使得winmgmts:成为非常简易和有力的脚本工具。
Set objLogicalDisk = _
GetObject("WinMgmts:Win32_LogicalDisk.DeviceId=’C:’")
通常,分号“:”隔离Winmgmts和对象路径,比如WinMgmts:Win32_LogicalDisk.DeviceId=’C:’.如果,你有安全设置,你必须使用“!”比如:WinMgmts:{impersonationLevel=impersonate}!Win32_LogicalDisk.DeviceId=’C:’
GetObject(“WinMgmts:”)
The SWbemServices object for the default namespace (root\cimv2) on the local computer.
GetObject(“WinMgmts://Instructor”)
The SWbemServices object for the default namespace (root\cimv2) on the instructor computer.
GetObject(“WinMgmts://Instructor/root/cimv2”)
The SWbemServices object for the specified namespace on the instructor computer.
GetObject(“WinMgmts:root/cimv2”)
The SWbemServices object for the specified namespace on the default server (Local).
GetObject(“WinMgmts: Win32_LogicalDisk.DeviceID = ‘C:’”)
The SWbemObject object for the instance of the logical drive C on the default server (Local).
GetObject(“WinMgmts: {impersonationLevel=impersonate}[locale=ms_409] !//Instructor/root/cimv2: Win32_LogicalDisk”)
The SWbemServices object for the specified namespace and object on the instructor computer by using the impersonate security setting and US English locale setting. Note that the exclamation mark is required to demarcate the object
path in this example.
注意,在使用中“//”和“\\”是通用的
4. Locator和moniker的比较
Object returned
使用locator对像的connectserver方法,仅返回SWbemService对象,需要另一个步骤的步骤取回一个SWbemObject对象。你必须采用被SWbemService支持的一种方法,比如Get方法:如下所示:
Set objLocator = CreateObject("wbemscripting.SwbemLocator")
Set objSvc = objLocator.ConnectServer()
Set objDisk_C = objSvc.Get("Win32_LogicalDisk.DeviceID=’C:’")
freeSpace = objdisk_C.freeSpace
Wscript.echo "The Free Space on C: is " & freeSpace
而采用winMgmts:moniker要更灵活,因为它可以即可以被用来返回SWbemService对象,也可以是直接返回SWbemObject对象。下面的例子,moniker被用来提交一个实际的实例,来反映逻辑磁盘c:
Set objDisk_C = _
GetObject("WinMgmts:Win32_LogicalDisk.DeviceID=’C:’")
freeSpace = objdisk_C.freeSpace
Wscript.echo "The Free Space on C: is " & freeSpace
Security
Locator和moniker机制都提供设置扮演,验证,授权和特权设置。
只有locator对象的connectServer方法当你链接的时候允许你使用不同的票证。在下面的例子中,当前登录的用户选择一个用户帐号,sysadmin,密码是password链接到server1的root\cimv2的名称空间
Set objLocator = CreateObject("wbemscripting.SwbemLocator")
Set objSvc = _
objLocator.ConnectServer("Server1",,"sysAdmin","password",,,)
Set objDisk_C = objSvc.Get("Win32_LogicalDisk.DeviceID=’C:’")
freeSpace = objdisk_C.freeSpace
Wscript.echo "The Free Space on C: is " & freeSpace
Winmgmts:moniker链接总是使用运行脚本用户的票证。这看起来似乎限制了使用moniker,但在实际上,大多数脚本由管理员运行,他往往不需要修改他的票证。
反而是,如果把用户和密码作为脚本的一部分,会引发安全隐患。
5.使用SWbemServices Object
Key Object for accessing WMI Features
无论脚本是用locator object,并且运行connectServer方法,或是使用winMgmts:moniker,结果是一样的。WMI返回一个SWbemServices对象的实例。
SWbemService对象可以被执行18种方法中的一种,并且提供WMI脚本管理的主要功能。
properties
SWBemService对象只有一个属性,security属性,用来对访问WMi进行设置验证,扮演和特权。
Class and Intances
一些方法返回类和实例,通常,你必须返回一个对象的实例,来读取它的属性。常见的例子包括空闲的磁盘空间,内存尺寸或网络IP地址等等,下面的例子是win32_process对象的实例,指明process ID 764的unique process
Set objSvc = GetObject("WinMgmts: ")
Set obj = objSvc.Get("Win32_process.handle=764")
Wscript.echo "Working Set: is " & obj.workingSetSize
但是,也有一些特殊的情况下,重要的是要取得类,而不是实例。举例来说,创建一个新的进程是一个类方法,不是一个实例方法。要运行一个新的进程,你必须因此而检索Win32_process类。在下面的例子中,一个类被返回,因为没有一个实例所指定的关键属性(处理)。
Set objSvc = GetObject("WinMgmts: ")
Set obj = objSvc.Get("Win32_process")
Result = obj.Create("calc.exe", null, null, processID)
二. 访问WMI对象
1、使用属性和方法
在脚本里,属性或方法是用点分隔描述的
类和类的实例有属性和方法,它们各不相同,WIM的SDK信息于此关联。
安装软件情景
你需要在远程系统上安装windows installer package(.msi file),要做到这,在安装前,你需要初始确认那计算机是否有足够的物理内存。
要在脚本中使用一个对象的属性和方法,要执行以下步骤
连接到WMI
提交一个SWbemServices对象
使用一个SWbemSerive对象的枚举方法来获得SWbemObject对象,来表示你所需要类或实例。
读取属性
执行方法
考虑咨询WMI SDK,有两个类需要了解Win32_ComputerSystem和Win32_Product.
检查物理内存
Win32_ComputerSystem有51个属性,没有方法,要使用TotalPhysicalMemory属性,采用下面方法:
Set objSvc = GetObject("winmgmts:\\Server1")
Set obj = objSvc.Get("Win32_computerSystem.name=Server1")
If obj.TotalPhysicalMemory > 267952128 Then ‘Must have 256MB
‘Go ahead and install
End If
安装一个Windows Installer Package
Win32_Product类,支持11个属性和7个方法,Install方法可以用来安装一个windows install packasge,它具有三个参数,并返回一个数值,指明安装是成功还是失败。下面是语法:
Product.install(PackageLocation,Options,AllUsers)
PackageLocation:是msi文件的完整路径,Options允许命令行的一些特殊选项(如果需要)。Allusers被设定为True或False,指明这个包是安装给所有的用户还是当前登录用户,默认是True。
在这里的例子,是一个简单的安装实例,.msi文件已经在本地,而其他参数没有加以设置
Set objSvc = GetObject("winmgmts:\\Server1")
Set obj = objSvc.Get("Win32_Product")
VLocationPath = "C:\source\scriptApp.msi"
retVal = obj.Install(VLocationPath)
比如:
管理DHCP客户的情景
情景:
你需要暂时将DHCP服务器从网络上移开一会,在这个时候,客户机无法更新地址,你决定赋予客户机静态地址,然后当服务器可用时,重新设置其为DHCP客户机。
这个任务要求访问每一个计算机,这有困难,所以可以使用WMI脚本
禁用DHCP客户
使用Win32_NetworkAdapterConfiguration包含属性和方法,有一些方法用来禁用DHCP,你通过设置静态地址来禁用DHCP,使用EnableStatic方法
Obj.enableStatic(IPAddress,SubnetMask)
下面是完整示例:
Set objSvc = GetObject("WinMgmts:")
Set obj = objSvc.Get _
("Win32_NetworkAdapterConfiguration.index=0")
ipaddr = Array("192.168.30.25")
subnet = Array("255.255.255.0")
RetVal = obj.EnableStatic(ipaddr,subnet)
注意,IPAddress和SubnetMask参数是一个数组,意味着可能有多个记录,一个网卡可能有多个地址等。
在Win32_NetworkAdapterConfiguration类中,有一个key property是index,当index=0,指的是第一张网卡。
启用DHCP
使用同一个类的EnableDHCP方法
Obj.enableDHCP()
下面是一个示例:
Set objSvc = GetObject("WinMgmts:")
Set obj = objSvc.Get _
("Win32_NetworkAdapterConfiguration.index=0")
RetVal = obj.EnableDHCP()
GET和实例方法
Get方法指定一个类或类的实例,为获得一个对象的实例,实例必须绝对确定,这表示你必须在脚本中为其提供一个辨识信息。在前面的例子中,你必须为特定的网卡进行网络设置。这个在WMI中用index number进行辨识。这个数字是在这个类中是key property。Get方法仅工作于key properties.
为获得一个对象的实例,实例必须绝对确定,这表示你必须在脚本中为其提供一个辨识信息。在前面的例子中,你必须为特定的网卡进行网络设置。这个在WMI中用index number进行辨识。这个数字是在这个类中是key property。Get方法仅工作于key properties
Instancesof方法被用于指明当前连接的名称空间的所有实例,返回一个集合,要用for each语法进行遍历
3.编辑属性值
可写属性
并不是所有的属性都可以改变的,比如Win32_Processor.currentClockSpeed(CPU的时钟频率),就算你修改这个cpu的时钟值为真实值的两倍,也不会加快系统的速度,所以,有些属性是只读的。
但是,有些属性是可以修改的,比如一个分区的volumeName,什么样的属性是可写的取决于底层的开发商。
但在多数情况下,该属性的的写特性被设置为True
使用Put_Method
如果你采用一个方法,用脚本获取一个对象,这个对象的数据存放在memory中,当这个对象被释放,就将丢失。要修改属性值,它必须先写入内存,然后提交到长久的存储设备,使用Put_方法。
虽然整个实例被提交到存储设备,但只有属性可修改才被改变。所有的其他的属性被简单忽略,不产生一个错误。
注意,你不能写一个对象key property。
使用场景:
要将所有的桌面计算机的分区名进行标准化的转换。
Set objSvc = GetObject("WinMgmts:")
Set obj = objSvc.Get("Win32_LogicalDisk.DeviceId=’C:’")
obj.VolumeName="System"
obj.Put_
4. Qualifiers(约束)
Qualifiers的目的是提供一种机制,使架构定义语言(schema definition language)在有限的和有控制的方式下进行扩展。
什么是qualifier
Qualifier告知用户类或属性的“语义”,但并不强制。强制是provider的责任。比如,Win32_VideoConfiguration.AdapterCompatibility属性有一个qulifier叫maxlen,设置为256.这指明了这个属性可以接受的最大字符串长度。
The Key Qualifier
如果一个属性的key qualifier设置为True,它被用来指示这个对象的唯一性,它和数据库表中的主键一个意思
valuemap和value
一个valuemap qualifier包含了某属性所有允许的值。这些值可能是整数也可能是字符串。
alueMap可以和Value qualifier进行映射
比如:
Win32_Processor.statusInfo有这样的valuemap和value
ValueMap Value
1 Other
2 Unknown
3 Enabled
4 Disabled
5 Not Applicable
Read/Write Qualifier
一些属性有读/写qualifiers,是布尔值,True或是False。这指示了该属性能够被更新。比如,Win32_LogicalDisk.volumeName属性有一个Write qualifier设置为True。
三. 高级脚本
1、错误处理
WMI错误
核心WMI错误-由WMIService所遇到的错误,被记录在Windows事件日志中,%SystemRoot%\System32\Wbem\Logs日志文件夹中。由HKLM\Software\Microsoft\Wbem\Cimom注册表控制.
WMI脚本API错误
由脚本应用程序接口调用所造成的错误,可以有自然的脚本语言机制加以处理。在visual basic或visual basic edition (VBSCRipt),错误处理由Err对象支持。这个对象有一个Description属性,用来包含错误描述。Number属性被设置为通过脚本API返回HRESULT。Source属性被设置为一个字符串,指明这个对象引发错误。
下面的示例脚本尝试对LogicalDisk对象调用一个不存在的方法“convert”,从而产生VBScript run-time错误。
On error resume next
Set objDisk =
GetObject("winmgmts:Win32_LogicalDisk.deviceID=’C:’")
retVal = objDisk.convert
If err<> 0 Then
WScript.Echo err.number, err.description, err.source
end if
这个错误生成下列结果:
Err Object Property Result
Number 438
Description Object does not support this property or method
Source Microsoft VBScript runtime error
返回代码
在WMI里,用一个32位的数字指定错误,0代表成功,通常执行脚本的错误源是COM+,RPC或WMI
错误代码如果是从com+或RPC调用引起的,则错误代码是x8007####,如果是WMI的错误,则是x8004###。
下面是一些错误示例,更完整的示例请参阅WMI SDK
Constant Number Description
WBEM_E_NOT_FOUND 0x80041002 The object could not be found.
WBEM_E_ACCESS_DENIED 0x80041003 The current user does not have permission to perform the action
WBEM_E_TYPE_MISMATCH 0x80041005 A type mismatch occurred.
SWbemLastError对象
在一个操作后(如果这个操作包含一个错误),SWBemlastError被明确的创建,用来收集额外的信息。如果Err对象指明了
一个错误发生,SWbemLastError对象立刻创建陷阱扩展信息,它在当前运行的线程,生成并返回最后的WMI扩展错误代码。
SWbemLastError对象是一个SwbemObject对象,它具有标准的SWbemObject对象的所有属性和方法,不过用实例或类的数据报
告来代替,SWbemLastError对象报告关于错误的数据报告,这个对象有一个read-once的语义,当错误报告属性被读过后,
这个语义就被清除。
下面一个示例显示如何使用SWbemLastError对象
On Error Resume Next
Set objSvc = GetObject("WinMgmts:")
Set objObject = objSvc.Get("NoSuchClass")
if Err = 0 Then
WScript.Echo "Got the class"
Else
set objObject = CreateObject("WbemScripting.SWbemLastError")
Set oPropSet = objObject.properties_
For Each oProp in oPropset
strLastError = strLastError & oProp.name & ": " & _
oProp.value & vbcrlf
Next
strErr = "Source: " & Err.Source & vbcrlf
strErr = strErr & "Description: "& Err.Description & vbcrlf
strErr = strErr & "Number: 0x" & Hex(Err.Number) & vbcrlf
MsgBox strErr,vbInformation,"From Err Object"
MsgBox strLastError,vbCritical,"From Last Error Object"
End If
2、SWbemObject
当一个合法的SWbemService对象被创建,你可以使用Get方法或InstancesOf方法来来检索任何在CIM中的类或实例模型
使用SWbemServics.Get方法来创建SWbemObject
下面的实力显示使用SWbemService的Get方法
Set objSvc = GetObject("WinMgmts:")
Set obj = objSvc.Get("Win32_LogicalDisk.DeviceID=’C:’")
通过Get方法返回的这个对象是SWbemObject对象,在前面的示例中,这个对象代表一个WMI对象,而这反过来代表一个可管
理对象,逻辑磁盘C。SWbemObject对象有它自己的属性和方法。这些都和WMI对象不同。比如,在这个例子中,obj对象没有
诸如Filesystem,FreeSpace或VolumeName等属性。SwbemObject的对象和方法总是以下划线结束。
检索WMI对象的属性
SWbemObject对象的Properties_属性是一个嵌入对象,这个对象是一个SWBemPropertySet对象,并且有自己的属性和方法,
它是一个SWbemProperty对象的个体的集合。SWbemPropertyd对象也有自己的属性,在这个例子里,没有方法。
SWBemPropertySet的Count属性是属于这个集合的SWbemProperty对象的数量。
在SWbemProperty对象的最重要的属性是Name和Value.匹配在基本的WMI对象的属性名上,并相关到相应的值。
要确定逻辑磁盘C的空闲空间,你必须首先通过Obj.properties_属性检索表明SWbemPropertySet对象,在下面的例子里,包
含了逻辑磁盘的所有属性,是一个集合。然后,你通过这个集合来检索SWbemProperty对象,来找到name属性等于FreeSpace
的,一旦这一目标已被确定,你就能阅读被称为SWbemProperty.Value的的相关属性信息了。
Set objSvc = GetObject("WinMgmts:")
Set obj = objSvc.Get("Win32_LogicalDisk.DeviceID=’C:’")
For each objProperty in obj.properties_
If objProperty.name = "FreeSpace" Then
vFreeSpace = "The " & objProperty.Name & " is " & _
objProperty.value & " Bytes"
End If
Next
MsgBox vFreeSpace, vbInformation, "Free Space on C:"
检索WMI对象使用的SWbemObject的属性
你也可以通过SwbemPropertySet对象的Item方法,来阅读特定的属性的值。下面是示例:
Set objSvc = GetObject("WinMgmts:")
Set obj = objSvc.Get("Win32_LogicalDisk.DeviceID=’C:’")
vFreeSpace = _
obj.Properties_.Item("FreeSpace").Value & " Bytes"
MsgBox vFreeSpace, vbInformation, "Free Space on C:"
3、方法
你通常通过在脚本中运行相关的methods(使用.来分割表示)。然而,SWBem脚本API也支持ExecMethod方法。
SWbemServices和SWbemObject对象支持方法,叫ExecMethod和ExecMethod_,它们各自可以运行WMI对象方法。
InParameters/OutParameters
SWbemObject.methods_属性仅被用于学习特征的一种方法,它不被用于执行一个方法,Methods_属性指向一个SWbemMethod对象的集合。这个对象反过来有属性,包括InParameters和OutParameters。这些都是内嵌SWbemObject对象。
SWbemObject.ExecMethod
通常的Execmethod_的语法是:
ExecMethod_(strMethodName,ObjInParms,iFlag,NameValueSet)
Parameter Explanation
strMethodName Required. The WMI objects method.
ObjInParms An SWbemObject object that has all the necessary input parameters specified for this method (if needed).
4.直接访问
执行方法
要直接访问一个对象的方法,你可以调用方法,就像它属于SWbemobject对象,下面的例子里,objMessengerSvc是一个SWbemObject对象,代表Win32_Service对象被称为Messenger。由点分割的stopService方法使其看起来是SWbemObject对象的一部分。
Set objMessengerSvc = _
GetObject("WinMgmts:win32_Service.name=’Messenger’")
retVal = objMessengerSvc.stopService()
If retVal = 0 Then
wscript.Echo " The messenger Service has been stopped"
Else
wscript.Echo "Error: " & retVal
End If
访问属性:
使用".",一个CIM对象属性可以被看作一个SWbemObject对象,比如:
Wscript.Echo "FreeSpace: " & _
disk.Properties_.Item("FreeSpace").value
Becomes:
Wscript.Echo "FreeSpace: " & disk.FreeSpace
Concise Script
结合使用默认设置,Monikers和直接访问“.”,代码可以更简洁方便明确。
Set locator = CreateObject("WbemScripting.SWbemLocator")
Set context = CreateObject("WbemScripting.SWbemNamedValueSet")
Set objSvc = locator.ConnectServer(".", "root/cimv2", "", _
"", "", "", 0, context)
Set disk = objSvc.Get("Win32_LogicalDisk.DeviceID=""C:""", _
0, context)
WScript.Echo "FreeSpace: " & _
disk.Properties_.Item("FreeSpace").Value
Using default settings, this example can be rewritten as:
Set locator = CreateObject("WbemScripting.SWbemLocator")
Set services = locator.ConnectServer()
Set disk = services.Get("Win32_LogicalDisk.DeviceID=""C:""")
WScript.Echo "FreeSpace: " & _
disk.Properties_.Item("FreeSpace").Value
Using a moniker, this example can be rewritten as:
Set disk = _
GetObject("winmgmts:Win32_LogicalDisk.DeviceID=""C:""")
WScript.Echo "FreeSpace: " & _
disk.Properties_.Item("FreeSpace").Value
Using direct access, it becomes:
Set disk = _
GetObject("winmgmts:Win32_LogicalDisk.DeviceID=""C:""")
WScript.Echo "FreeSpace: " & disk.FreeSpace
Achieving the same result on one line, the example finally becomes:
Wscript.echo FreeSpace: & GetObject _
(winmgmts:Win32_LogicalDisk.DeviceID=""C:""").FreeSpace
5、同步方法
同步方法
方法可以运行于三种方式之一
同步:
默认情况,调用脚本等待操作结束。这是最简单的模式,但有时候,却不适合,比如网络连接多个远程主机,在这种情况
下,就必须考虑延时的情况,因此,脚本可能显得停止了响应。
举例:
一个脚本连接到多个服务器,在那些服务器上执行一些操作,同步操作意味着只有等server1完成所有操作后,server2才
开始操作,如果server1 down掉了,这样,脚本会被延时。
另一个同步示例:要列举很多数量的对象,比如要列举事件日志,脚本看上去就像没有反应一样,即使在一个本地系统上
,联系一个10000个记录可能需要很多时间。
异步
一个可选的动作是立刻给调用脚本控制权,更使其平行的运行一个操作线程,当初始的调用结束,异步操作调用
OnCompleted事件。你可以使用异步方法,用于任何需要长时间完成的任务。比如查询一个时间通知。所有剩余的数据被放
置在Windows Management Service的内存中,通常,这不会引起什么问题,但是如果返回的数据非常大,这种机制可能引
起“溢出内存”错误。
比如,获取10000个事件记录可能需要30秒,这个脚本在此期间执行其他的任务。60000条记录可能引起256M计算机的“Out
of Memmory”问题。
半同步
半同步操作是最简单的解决方法,是前两种方法的折中。(同步引起的延迟的复杂性和异步调用性能限制之间的平衡)
半同步解决的是(同步)连个线程阻塞和(异步)不加控制的交付问题。
要设置半同步执行,你需要检查下面两个标志和值:
Flag Value Description
--------------------------------------------------------------------------------
WbemFlagReturnImmediately 16 Returns control immediately to the calling script
WbemFlagForwardOnly 32 Returns each result as and when it arrives
标志参数是Anded计算最后的值,在这个例子里,两个标志值都设置过,则十进制的值是48
InstancesOf和ExecQuery方法都可以以半同步方式运行。
数据被获得和返回,但是代替掉在Windows management service中累积的做法,它一项一项的转发给脚本,这意味着脚本
处理这些项目,就像它们已经返回了一样。因此,不象同步操作,当数据获得的时候脚本不暂停。并且也不象异步操作,
它可以处理返回的项目,当它们出现的时候。
比如,获得10000事件日志记录,可以在30秒钟之内执行,60000条记录只需要1到2分钟。
在下面的示例中,WMI查询服务检索应用程序日志数据数据,其中的48就是半同步操作标志
On Error Resume Next
For Each obj in GetObject("WinMgmts:").ExecQuery _
("Select * From Win32_NtLogEvent Where _
LogFile=?Application?",,48)
count = count + 1
Next
If Err<> 0 Then
Wscript.echo "Something went wrong"
End If
Wscript.echo count
6、SWbemSink Object
SWbemSink对象
SWbemSink对象被用于处理异步操作和事件
异步的脚本调用:
以下四个步骤说明如何实现异步方法调用
1.创建一个接收器对象,当调用异步方法时通过它作为参数调用。
Set objSvc = GetObject("WinMgmts:")
Set mySink = _
WScript.CreateObject("WbemScripting.SWbemSink","SINK_")
RetVal = objSvc.InstancesOfAsync(mySink,"Win32_process")
2.当OnObjectReady事件被触发,写例程被执行
Sub SINK_OnObjectReady(objObject, objAsyncContext)
WScript.Echo (objObject.Name)
End Sub
3.当OnCompleted事件被触发,写常规被出发
Sub SINK_OnCompleted(iHResult, objErrorObject, _
objAsyncContext)
WScript.Echo "Asynchronous operation is done."
End Sub
4.通过写代码可以推迟脚本终止足够长的时间,异步调用即可开始使用。如果脚本继续执行,而其他地方的异步任务继续
执行完成,而脚本本身终止,将引起异步数据将丢失。为了防止这个情况发生,脚本必须等到异步任务完成才终止,一个
最简便的方法,就是弹出个对话框,然后要手动的按“确定”。如下:
WScript.Echo "Waiting for instances."
要取消未异步调用,可以使用SWbemSink.cancel方法。将SWbemSinkObject设置为Nothing,是不够的。
举例:
Part of a larger script
Set sink = _
wscript.CreateObject("WbemScripting.SWbemSink","SINK_")
start the asynchronous method here
carry on with some other process here
If err<>0 Then
There must have been an error so we will stop
everything
Set sink = nothing doesnt work here so call cancel
sink.cancel()
End If
OnCompleted
当异步调用结束,OnCompleted事件将被触发。它通知客户端应用程序异步操作的结果,或提供异步调用的错误信息。它返
回下列三个参数:
IHresult:0代表成功,非0代表失败
SWbemLastError:一个包含最后遇到错误细节信息的对象
SWbemNamedValueSet:用来区分异步操作的一个对象,用在如果多个操作共享相同的sink对象的时候。
OnObjectPut
当一个异步调用写入对象的时候,OnObjectPut事件触发,该事件返回两个参数:
SWbemObjectPath:被保存的实例或类的对象路径
SWbemNamedValueSet:如果多个操作共享同一个sink对象,异步操作的辨识。
OnObjectReady
如果异步调用返回一个对象,则触发OnObjectReady事件。比如,InstancesOfAsync或ExecqueryAsnc方法会返回一个或多
个对象。同步版本的这些方法返回一个单一对象集,包含所有对象的结果,异步版本的方法一次返回同一对象一次。返回
的参数如下:
SWbemObject:返回对象
SWbemNamedValueSet:如果多个操作共享同一个sink对象,异步操作的辨识。
OnProgress
当一个异步调用被要求设置它自己的iFlags参数来报告前进状态,Onprogress事件将被触发。返回参数如下:
IUpperBound:一个整数,用来描述完成任务的总数量
ICurrent:本项目中的任务列表正在处理中
StrMessage:字符串信息,描述当前的任务的状态
SWbemNamedValueSet:如果多个操作共享同一个sink对象,异步操作的辨识。
举例:
On Error Resume Next
Dim strName
Set objRemoteSvc = GetObject("WinMgmts:\\Server1")
Set sink = _
wscript.CreateObject("WbemScripting.SWbemSink","SINK_")
’We expect this remote fetch to be slow so we will run it
’offline’
retVal = objRemoteSvc.InstancesOfAsync( sink,"Win32_Share")
’Now we carry on with some other work. In this example
we will just pause the script here while the instancesOf
method runs asynchronously elsewhere.
Wscript.Echo "Wait here until finished"
Wscript.Echo StrName
Wscript.Quit
’-------- only subroutines below this line --------------
Sub SINK_OnCompleted(iHResult, objErrorObject,
objAsyncContext)
Wscript.echo "Ok the asynchronous task has finished"
End Sub
Sub SINK_OnObjectReady(objObject, objAsyncContext)
strName = strName & _
" Folder " & objObject.Path & " is shared as " & _
objObject.name & vbcrlf
End Sub
--------------------------在这个例子中的一系列事件如下:---------------------
1. The scripts connects to the remote WMI service.
2. The script creates a sink object.
3. The script calls the InstancesOfAsync method to fetch all the shares.
4. The script continues running and displays Wait here until finished.
5. In the meantime, WMI has retrieved the data and feeds each object to the OnObjectReady subroutine where
they are processed.
6. Finally, when the asynchronous call has finished, WMI notifies the
OnCompleted subroutine, which displays the message Ok the asynchronous task has finished.
7. After closing both of the message boxes, the script continues and displays the strName sting containing all of the data.
7、创建新的实例
有时,创建一个完整新的对象实例是有用的,对于大多数Win32 provider的类,这没有意义。
比如,创建一个新的win32_processor类的实例,并不能给系统带来一个额外的cpu。它只是建立一个新的在WMI对象,这看起来是一个处理器。事实上,这中类型的对象是只读的,并且不能通过脚本创建。
唯一相关的一些Providers
通过其他的一些providers,创建某些类新的实例才是更有意义的。比如,SQLAdmin Providers提供在WMI中创建数据库,数据表,触发器,索引的能力;在SMS中,提供创建Package、Program、Advertisement的能力。你可能还记得,这种统一管理的方法是WMI的目标。
SpawnInstance_方法
要通过WMI脚本API创建(类的)新的实例,一个对象通过适合的类得到。其次,通过运行SpawnInstance_方法,一个空的SWbemObject对象被创建。
Populate the Properties
空对象的属性被值填充,对象的属性和它相关的值由创建的类的对象决定,这个信息可以在WMI SDK中获得,并不是所有的属性都要填充,但key properties必须填。
The Put_ Method
当所有的属性被填充后,这个对象通过Put_方法被写回CIM
下面的示例是创建一个EventConsumer实例
Set objSvc = GetObject("WinMgmts:")
Set objConsumerClass = objSvc.GET("ActiveScriptEventConsumer")
Set myInstance = objConsumerClass.spawninstance_
myInstance.name = "writeToFile"
myInstance.ScriptingEngine = "VBScript"
myInstance.ScriptFileName = "C:\Program _
Files\MsdnTrain\2439\Labs\Lab04.2\writeToFile.vbs"
myInstance.ScriptText = NULL
myInstance.KIllTimeout = 30
myInstance.put_
下面示例显示如何创建一个SQL用户定义的数据类型
Set UDTClass = GetObject _
("winmgmts://./root/MicrosoftSQLServer:MSSQL_UserDataType")
Set UDT = UDTClass.SpawnInstance_
UDT.SQLServerName = "MySQL"
UDT.DatabaseName = "Northwind"
UDT.Name ="MyUDTTest"
UDT.BaseDatatype ="int"
UDT.AllowNulls = False
UDT.Put_
四.安全设定
1.身份验证
有时,在进入WMI对象时,需要设置安全设置。当你第一次连接到WMI的时候,是实现这个目标的最方便的时机,然后可以确保所有随后的操作使用相同的设置。
AuthenticationLevel属性
这个属性是一个整形数,定义了一个对象被赋予的身份验证级别。对于远程连接,最小的设置是Connect,但这种只提供最低限度的安全。下面的表描述了设置:
Value Moniker label Description
0 Default WMI uses the default Windows authentication setting.
1 None Uses no authentication.
2 Connect Authenticates the credentials of the client only when
the client establishes a relationship with the server.
3 Call Authenticates only at the beginning of each call when
the server receives the request.
4 Pkt Authenticates that all data received is from the
expected client.
5 PktIntegrity Authenticates and verifies that none of the data
transferred between client and server has been
modified.
6 PktPrivacy Authenticates all previous authentication levels and
encrypts the argument value of each remote procedure
call.
参考下列代码:
Set objSvc = _
GetObject("WinMgmts:{authenticationLevel=PktPrivacy}")
从表中可以看出,最好的安全是PktPrivacy设置所提供的,它可以确保没有spoofing欺骗,客户端是经过验证的,而所有传递的参数都是加密的。
你可能还记得,可以使用ConnectServer方法将名称和密码作为参数发送,而这个帐号可能是Administrator,而这显然是很重要的,这些细节不能被网络嗅探工具所截获。
2、扮演
每个WMI连接使用一个扮演设置,
网管运行一个脚本,来访问的WMI。WMI service运行于Local System account,并调用合适的provider,扮演用户运行,目标设备和软件的访问权限由ACL控制。
一个被赋予到对象上的DCOM扮演级别属性是一个整数,此属性定义了进程所拥有的WMI在调用其他进程时,是否可以检测或使用您的安全凭据。
level 3,或扮演,是访问WMI的最低值。版本1.5设置默认扮演级别在下面的注册表:
HKLM\Software\Microsoft\Wbem\Scripting\DefaultImpersonationLevel
出于这个原因,1.5版本不需要设置扮演级别,但是,为了兼容老版本的WMI,和未来的发展,最佳做法是明确规定扮演值(Impersonate),下面的列表说明了扮演值的设置:
Value Moniker label Meaning
1 Anonymous Hides the credentials of the caller. Calls to WMI may
fail with this impersonation level, because the provider
may not have permissions to access resources.
2 Identify Allows objects to query the credentials of the caller.
Calls to WMI may fail with this impersonation level,
because the provider may not have permissions to
access resources.
3 Impersonate Allows objects to use the credentials of the caller. This
is the recommended impersonation level for WMI
Scripting API calls.
4 Delegate Allows objects to permit other objects to use the
credentials of the caller. This impersonation, which
will work with WMI Scripting API calls, but may
constitute an unnecessary security risk, is only
supported by Windows 2000.
下面的示例显示了怎么操纵扮演
Set objSvc = _
GetObject("WinMgmts:{impersonationLevel=impersonate}")
下面的示例显示怎么操纵验证和扮演
Set objSvc = GetObject("WinMgmts:_
{impersonationLevel=impersonate,_
authenticationLevel=PktPrivacy}")
3、授权和特权
授权和特权
设置连接的WMI可以指定授权的使用和用户权限。
授权
与WMI可以配置为使用Windows NT NTLM身份验证或Kerberos的机制,为所需的认证帐户和密码的脚本上下文。如果不指定
授权机制,WMI使用计算机访问默认的身份验证机制。
示例:
Set objSvc =
GetObject("WinMgmts:{authority=kerberos:mydomain\server}")
Set objSvc = GetObject("WinMgmts: _
{authority= authority=ntlmdomain:mydomain\server}")
特权:
当用户使用脚本尝试访问某种类型的资源时,他们必须有合适的权利。要做到这一点,该账户在本地计算机上必须有用户
权限,而脚本必须包含准备授予的明确权限。换句话说,你不能在脚本中指定不存在账户的特权。
下面的例子是赋予用户“Force Shutdown From A Remote System”的权利
Set objSvc = GetObject("WinMgmts:{(RemoteShutdown)}")
Set objSet = objSvc.ExecQuery _
("select * from Win32_OperatingSystem Where Primary=’True’")
For each OpSys in OpSysSet
OpSys.Reboot()
Next
对于远程连接,这不是一个问题,换句话说,DCOM保证,如果正在运行的账户在目标计算机上具有所需的用户权限,脚本
不需要再设置特权。
这是26个当前的特权(这个慢慢在增加)
下面的例子是设置Debug特权
Set objService = GetObject("WinMgmts:_
{impersonationLevel=impersonate, (Debug)}")
下面的例子是赋予Debug的权利,取消RemoteShutdown的权利,注意,前面的“!”,这个符号是否定的意思。
Set objService = _
GetObject("WinMgmts:{impersonate,(Debug,!RemoteShutdown)}")
Constant Value (Dec) Description
CreateToken 1 Required to create a primary token.
PrimaryToken 2 Required to assign the primary token of a process.
LockMemory 3 Required to lock physical pages in memory.
IncreaseQuota 4 Required to increase the quota assigned to a process.
MachineAccount 5 Required to create a machine account.
Tcb 6 Identifies its holder as part of the trusted computer
base. Some trusted, protected subsystems are
granted this privilege.
Security 7 Required to perform a number of security-related
functions, such as controlling and viewing audit
messages. This privilege identifies its holder as a
security operator.
TakeOwnership 8 Required to take ownership of an object without
being granted discretionary access. This privilege
allows the owner value to be set only to those
values that the holder may legitimately assign as
the owner of an object.
LoadDriver 9 Required to load or unload a device driver.
SystemProfile 10 Required to gather profiling information for the
entire system.
Systemtime 11 Required to modify the system time.
ProfileSingleProcess 12 Required to gather profiling information for a single process.
IncreaseBasePriority 13 Required to increase the base priority of a process.
CreatePageFile 14 Required to create a paging file.
CreatePermanent 15 Required to create a permanent object.
Backup 16 Required to perform backup operations.
Restore 17 Required to perform restore operations. This
privilege enables you to set any valid user or group
security identifier (SID) as the owner of an object.
Shutdown 18 Required to shut down a local system.
Debug 19 Required to debug a process.
Audit 20 Required to generate audit-log entries.
SystemEnvironment 21 Required to modify the nonvolatile random access
memory (RAM) of systems that use this type of
memory to store configuration information.
ChangeNotify 22 Required to receive notifications of changes to
files or directories. This privilege also causes the
system to skip all traversal access checks. It is
enabled by default for all users.
RemoteShutdown 23 Required to shut down a system using a network request.
Undock 24 Required to remove the computer from docking station.
SyncAgent 25 Required to synchronize directory service data.
EnableDelegation 26 Required to enable computer and user accounts to be trusted for
delegation.
4、使用SWBemSecurity对象
许多SWbem脚本API对象有Security_属性
使用SWbemSecurity对象设置安全
SWbemLocator, SWbemServices, SWbemObject, SWbemObjectSet,SWbemObjectPath, SWbemLastError和SWbemEventSource对象每一个都有一个属性叫Security_,这本身是一个嵌入对象类型,SWbemSecurity。这个类的对象没有方法,但以下三个重要属性。
AuthenticationLevel
ImpersonationLevel
Privileges
下面的例子显示如何操作AuthenticationLevel属性
Const wbemAuthenticationLevelPktPrivacy = 6
objMyObject.Security_.AuthenticationLevel = _
wbemAuthenticationLevelPktPrivacy
下面的例子说明如何制定扮演等级
Const wbemImpersonationLevelImpersonate = 3
objMyObject.Security_.ImpersonationLevel = _
wbemImpersonationLevelImpersonate
下面的例子说明如何指定特定的权利级别
Const wbemPrivilegeDebug = 19
objMyObject.Security_.Privileges.Add wbemPrivilegeDebug, True
下面的例子是另一种方式指定的特权级别的方法
objMyObject.Security_.Privileges.AddAsString _
("SeDebugPrivilege,True")
在前面的两个例子中,可以通过使用wbemPrivilegeDebug constant的Add方法指定设置,或NT和windows 2000constant SeDebugPrivilege的AddAsString方法来设置。
SWbemSecurity对象的Privieges_属性是一个SWbemPrivilegeSet对象,它用来使能或禁用Windows NT或Windows 2000特权.您可能需要设置这些权限,才能通过WMI脚本使用的API执行特定任务的,如检查安全日志或执行系统关机