WMI Scripting with AutoIt.docx
《WMI Scripting with AutoIt.docx》由会员分享,可在线阅读,更多相关《WMI Scripting with AutoIt.docx(27页珍藏版)》请在冰豆网上搜索。
WMIScriptingwithAutoIt
WMIScriptingwithAutoIt
Feb.02,2009inGeneral
Share
0
Iwaspresentedwithaninterestingproblemwhileatworktoday…..IneededtogetthemotherboardmanufacturerandmodelofeveryWindows-basedPConournetwork,andIfiguredthebestwaytodothisiswithaWMIquery.IcouldquicklyandeasilyputtogethersomekindofscriptthatcouldremotelyexecuteaWMIqueryoneverycomputer.WhatisWMI?
MicrosoftWindowsManagementInstrumentation.ItistheMicrosoftimplimentationofWeb-BasedEnterpriseManagement(WBEM)whichusestheCommonInformationModel(CIM).WMIconnectionsaremadeusingtheDistributedComponentObjectModel(DCOM).
Whatdoesitdo?
Itallowsforremotemanagementofprocesses,services,registryhives,filesystems,eventlogs,scheduledtasks,filesandfolders,etc.andallowsyoutogatherinformationaboutcomputerhardware,software,network,datesandtimes,etc.,etc.Youcanevenremotelyexecuteprocesses.
HowdoIgetit?
Thatpartiseasy.Ifyou’reusingMicrosoftWindowsandyouhaven’tbeenlivinginthestone-age,thenyouprobablyalreadyhaveit.ItwasintroducedinMicrosoftWindows2000startingwithServicePack2.ItcanalsobeaddedtoearlierversionsofWindowsbyinstallingthe.NETFrameworkSDKandRedistributablepackage.Sochancesare….youalreadyhaveit.
HowdoIuseit?
Well,thereisawealthofinformationonthissubject.Forthepurposesofthisdiscussion,we’llfocusonqueries.ThequerysyntaxisasubsetofSQLcalledWQL.IfyouarefamiliarwithSQL,you’llfindthistobetrivial.Youcansimplypass“SELECT…FROM”statementstotheExecQuery()methodtoreturntherequestedinformation.Butfirst,youneedtoinstantiateaconnectiontothelocalorremotemachine.ThisistypicallydoneviatheCOMAPIforWMI.SoanyCOM-capablelanguagesuchasVB6,PowerShell,C++,.NET,PowerShell,WinBatch,AutoItV3,andsoon(includingASP)canmakeeasyuseofthisinterface.YoucanusemanagedcodetoimplimentWMIprovidersin.NETFramework3.5.
Formypurposes,IchosetowriteanAutoItscript.UsingtheObjGet()functionIcreateaconnectiontoremotecomputerlikeso:
$objWMI=ObjGet("winmgmts:
\\localhost\root\CIMV2")
Note:
replace“localhost”withthenameorIPoftheremotecomputeryouwanttoquery.Using“localhost”or“127.0.0.1″willexecuteonthelocalmachine.
WecannowqueryallattributesoftheWin32_ComputerSystemobjectclass:
$objItems=$objWMI.ExecQuery("SELECT*FROMWin32_ComputerSystem","WQL",0x10+0x20)
Noticethe2flagsattheend….0×10=ReturnImmediately,0×20=ForwardOnly.Youcouldassignthesetovariablesforbetterreadability.
$wbemFlagReturnImmediately=0x10
$wbemFlagForwardOnly=0x20
Andthenaddthemtogetherusingthe“+”operatortocombineflagvalues.Nowfromherewecangettheobjectattributes:
IfIsObj($objItems)Then
For$objItemIn$objItems
ConsoleWrite("Manufacturer:
"&$objItem.Manufacturer)
ConsoleWrite("Model:
"&$objItem.Model)
ConsoleWrite("Name:
"&$objItem.Caption)
ConsoleWrite("Description:
"&$objItem.Description)
Next
EndIf
Yougetthepoint.It’sthateasy.Ifyou’dlikeamoredetailedexample,I’vemadetheprojectIusedatworkavailablefordownload.JustclickontheitemunderAutoItV3called“WMI_ComputerSystemQuery”.Theexampleprojectincludesthemainscriptandacompiledconsoleapplicationalongwithdependenciesanddocumentation.
FormoreinformationonWMIandhowtouseit,checkoutthisMSDNarticle:
2Commentson“WMIScriptingwithAutoIt”
PeterZoll
February18th,2009at9:
12am
Wedidmuchthesamething–wedidfindthatanumberofoldermachinesrunningXPhadnullvaluesinoneormorefields.Whatwedidnotfindwasafieldwithachipsetname
likeX38,G41,955X…–thenamesthatInteluses.WelookedthroughmostofWMI–ifseemsifthechipsetnameisnotinComputerSystemoritschilditmustbewellhidden.Didyouhaveanybetterluckwithchipsetnamesonyourcomputers?
admin
February18th,2009at5:
45pm
Well….thatwasoneofthethingsI’dhopedtoextrapolatefromthistypeofquery.IlookedintoqueryingtheWin32_BIOSclass,butjudgingbytheMSDNdocumentation,itdoesn’tlooklikeyoucangetthechipsetfromit.I’mthinkingthiscouldprobablybeaccomplishedbyqueryingtheWin32_SystemDevicesclass….thoughIhaven’tfiguredoutexactlyhowyet.Forus,gettingthe“Model”propertyfromtheWin32_ComputerSystemclasshasbeensufficientbecauseweusemostlyIntelandSuperMicromotherboards.The“Model”propertyfortheseboardstypicallyreturnsavalidmodelthatwecanthenlookupandgetthespecson.InthecaseofIntel,thechipsettypicallymakesuppartofthemodelname,like“D946GZ”forexample.Inthiscase“D946GZ”tellsmethatit’sadesktop-classboardandusestheIntel946-serieschipset.
MostofthetimethisisalltheinformationIneed,butI’mquitesurethereisamoreaccurateapproach.Ijusthaven’tfoundityet.
在Autoit中使用WMI:
第一部分原文地址:
...8005b3cb130c1a.html
一、什么是WMI
WMI是Windows2K/XP管理系统的核心;对于其他的Win32操作系统,WMI是一个有用的插件。
有了WMI,工具软件和脚本程序访问操作系统的不同部分时不需要使用不同的API;相反,操作系统的不同部分都可以插入WMI。
也就是说,利用WMI我们能更方便地管理Windows资源—例如磁盘、事件日志、文件、文件夹、文件系统、网络组件、操作系统设置、性能数据、打印机、进程、注册表设置、安全性、服务、共享、用户、组等等。
。
二、对WMI中一些名词的解释
首先看到下面的一个例子,这段代码能够输出物理内存的大小(不是用已有的函数):
[language=autoit]$strComputer="."
$wbemServices=ObjGet("winmgmts:
\\"&$strComputer&"\root\cimv2")
$wbemObjectSet=$wbemServices.InstancesOf("Win32_LogicalMemoryConfiguration")
For$wbemObjectIn$wbemObjectSet
ConsoleWrite("TotalPhysicalMemory(kb):
"&$wbemObject.TotalPhysicalMemory)
Next[/language]
在对代码解释前,我先解释一下一些名词的含义:
对象:
所谓对象,就是建立COM组件时的返回值,像$wbemServices就是,我们称之为SwbemServicesWMI服务对象,至于$wbemObjectSet则叫做SwbemObject类实例集合对象,后文我还会提到SwbemLocator教本库对象。
它们的层级关系如下:
SwbemLocator教本库对象→SwbemServicesWMI服务对象→SwbemObject类实例集合对象→SwbemObject类的实例。
属性:
以$wbemServices.InstancesOff为例,我们就说$wbemServices对象的InstancesOff属性。
类:
WMI能实现的操作有很多种,不同种类的操作都是分开的,我们称之为类,上面代码中的"Win32_LogicalMemoryConfiguration"就是一个类。
命名空间:
类也分很多种,功能相近的类分在一起就是命名空间,比如说上面代码中的\root\cimv2。
而另一个常用的命名空间是root\DEFAULT。
例如,事件日志、性能计数器、Windows安装程序和Win32提供程序都存储在root\cimv2命名空间中。
另一方面,注册表提供程序存储在root\DEFAULT命名空间中。
集合:
$wbemObjectSet的数据类型属于集合,用FOR...IN...能对其进行列举。
三、使用WMI的基本步骤
1.获取SwbemServicesWMI服务对象,或者说连接到目标计算机的命名空间
[language=autoit]$strComputer="."
$wbemServices=ObjGet("winmgmts:
\\"&$strComputer&"\root\cimv2")[/language]
2.获取类的对象
[language=autoit]$wbemObjectSet=$wbemServices.InstancesOf("Win32_LogicalMemoryConfiguration")[/language]
3.使用指定对象的属性进行操作
[language=autoit]For$wbemObjectIn$wbemObjectSet
ConsoleWrite("TotalPhysicalMemory(kb):
"&$wbemObject.TotalPhysicalMemory)
Next[/language]
上面三步仅仅是对WMI操作的概括,实际操作时每一步都很复杂,下面将对这3步逐一进行讲解。
四、连接到命名空间的方法
方法1.用moniker名字法建立WMI服务的连接
这一方法也就是本文的例子所用到的,它的要点就是通过编写一个moniker字符串作为ObjGet函数的参数,然后返回一个SwbemServices对象。
关于moniker字符串的完整格式如下:
"winmgmts:
[{SecuritySettings}!
][\\ComputerName][\Namespace][:
ClassName][.KeyProperty='Value']"
"winmgmts:
"是前缀,表示为WMI服务,必须使用;第二部分用来验证权限和假冒级别的,省略。
第三部分为计算机名字:
"\\.\"是本机的计算机名字,默认可省略,,其余同上;第四部分命名空间:
缺省的命名空间为"root\CIMV2",默认可省略。
也就是说我给的那个例子中的相关代码可简写为:
$wbemServices=ObjGet("winmgmts:
"),但我绝不建议这样做。
第五部分为类名。
第六部分为属性值。
注意:
当该moniker字符串不包括最后2项时(即为:
"winmgmts:
[\\ComputerName][\Namespace]"),则ObjGet(moniker字符串)返回的是一个命名空间的已验证的连接(SwbemServices对象);当不包括最后1项时,返回的是一个类(SWbemObject对象);当包括最后2项时,返回的是一个类的单独实例(SWbemObject对象)。
方法2.通过建立SwbemLocator对象
这第二种方法我并不推荐,因为操作很繁琐,但是这种方法却能直观反应WMI操作的原理。
下面是具体步骤:
1.建立SwbemLocator对象
[language=autoit]$objLocator=ObjCreate("WbemScripting.SWbemLocator")[/language]
2.通过ConnectServer属性登录到目标计算机,下面的代码是登录到本机
[language=autoit]$objService=$objLocator.ConnectServer(".","root\cimv2")[/language]
3.设置impersonation等级
[language=autoit]$objService.Security_.ImpersonationLevel=3[/language]
5.执行你的代码,还是以显示物理内存为例
复制内容到剪贴板代码:
$objLocator=ObjCreate("WbemScripting.SWbemLocator")
$objService=$objLocator.ConnectServer(".","root\cimv2")
$objService.Security_.ImpersonationLevel=3
;和第一个例子不同,这里使用了ExecQuery属性来获取Win32_LogicalMemoryConfiguration类的对象
$wbemObjectSet=$objService.ExecQuery("SELECT*FROMWin32_LogicalMemoryConfiguration")
For$wbemObjectIn$wbemObjectSet
ConsoleWrite("TotalPhysicalMemory(kb):
"&$wbemObject.TotalPhysicalMemory)
Next
五、获得类的集合对象的方法
方法1.使用InstancesOf方法
InstancesOf方法的语法参数格式如下:
SwbemServices.InstancesOf(strClass)
strClass为类名,例如"Win32_Service"。
范例:
$wbemObjectSet=$wbemServices.InstancesOf("Win32_Service")
我在第一个例子里就是用这种方法来获取Win32_LogicalMemoryConfiguration类的实例集合。
方法2.使用ExecQuery方法
与InstancesOf方法不同,ExecQuery方法可以通过查询语句,只返回匹配部分实例和属性。
ExecQuery方法的语法参数格式如下:
SwbemServices.ExecQuery(strQuery,[strQueryLanguage="WQL"],[iFlags],[objWbemNamedValueSet]
strQuery为WQL(WMIQueryLanguage)查询的字符串,具体语法可以查看这里,下面是几个例子:
SELECT*FROMWin32_LogicalDisk;即获取Win32_LogicalDisk类的全部集合对象
SELECT*FROMWin32_NTLogEventWHERELogfile='Application",,48;从Win32_NTLogEvent类中获取名为"Application"的全部实例
SELECT*FROM__InstanceModificationEventWITHIN10WHERETargetInstanceISA'Win32_Service'ANDTargetInstance._Class='win32_TerminalService';当Win32_NTLogEvent有新的实例建立时发出通知(这属于WMI事件,具体内容后文再提)
而ExecQuery方法的后几个参数很少会用到,有兴趣的话可以在这里了解更多。
使用范例:
$wbemObjectSet=$wbemServices.ExecQuery("select*fromWin32_Service")
方法3.使用Get方法
和上面两种方法不同,Get方法获得的是单个的对象。
比方说,下面的代码能列举出全部的系统服务:
$strComputer="."
$wbemServices=ObjGet("winmgmts:
\\"&$strComputer&"\root\cimv2")
$wbemObjectSet=$wbemServices.InstancesOf("Win32_Service")
For$wbemObjectIn$wbemObjectSet
ConsoleWrite("Name:
"&$wbemObject.Name&@CrLf&_
"DisplayName:
"&$wbemObject.DisplayName&@CrLf&_
"Description:
"&$wbemObject.Description&@CrLf&_
"PathName:
"&$wbem