◎WMI輕松入門之一
一、基本概念
其實我給文章起這樣的名字,絕對沒有輕視WMI的意思,事實上就連微軟也有“WMI非常難于學習而且更難于使用”的說法,在近日的學習過程中更感覺到了WMI檢索功能的強大,之是以起個“輕松入門”的名字,我隻是有感于外國人寫教程在思路上和國人不太一緻,西方式的幽默看起來困難無比,再加上一上手就在類的基本結構上展開讨論,吓跑了無數Vbs的愛好者,想從國人常見的角度出發來說說怎麼學習WMI而已。百度空間的長度限制太讨厭了,一次發不完,隻好分割成三部分,題目隻能大緻起了,見諒。
一、什麼是WMI?微軟有很多說法,大家可以到腳本中心查閱,我這樣了解,WMI是一個用于管理Windows系統資源的對象,其内部應是一個樹狀的資料庫,資料庫中包含了很多個分支,每個分支被稱作命名空間,每個命名空間包含了很多個對托管資源的抽象定義,這種定義叫做類。在很多計算機教材中喜歡把類比作建築藍圖,依據藍圖建造的樓宇叫做類的執行個體,我更喜歡将類和其執行個體的關系比作表格,類就是表格的字段定義,而表中的資料就是一個個的類的執行個體,也許我這樣說會讓很多朋友更加糊塗,
但是依此類推,WMI中最終存在的是各種軟硬體資源的抽象定義,我們利用WMI,就是要按圖索骥,通過類定義,獲得類執行個體,檢索出符合要求的屬性,調用其内置的方法,實作我們的目标。相信很多朋友已經發現,我将WMI等同于CIM庫了,我清楚他們不是一回事,但我相信這樣更容易了解。如圖:
二、WMI的基本結構
嚴格說來,WMI由四部分組成:
1、 公共資訊模型對象管理器——CIMOM
2、 公共資訊模型——CIM
3、 WMI提供程式
4、 WMI腳本對象庫
其中其第1、2、3三個部分,在使用中很少加以差別,我們一般統稱為CIM庫。
是以我們可以認為WMI實際是由兩部分組成:CIM庫和WMI腳本對象庫。在具體使用過程中,我們是通過WMI腳本對象庫去通路CIM庫,管理托管的資源。也就是說,在我們編寫腳本的過程大緻可以分為這麼幾步:
1、 建立WMI對象腳本庫的指針執行個體;
2、 調用其執行個體的方法,連接配接到CIM庫,并指明需要通路的資源的邏輯位置;
3、 獲得托管資源也就是類的執行個體的集合;
4、 枚舉執行個體,完成工作。
這幾個步驟在我們将來編寫的代碼中可以明确的反映出來。
三、常用的命名空間
命名空間是個很複雜的概念,相信在微軟的網站上一定有很多的篇幅介紹這個概念,據我個人了解,命名空間是對類所處邏輯位置的一個約定。打個比方說:張家也有個孩子叫小強,李家也有個孩子小強。大家站在一起,你大聲叫"小強",你說這到底是叫哪一個小強呢?張家,李家都是一個姓,一個人的姓實際上就是現實中的一種名字空間。好了,現在你大聲叫“張小強”,我們就明确的知道你到底是叫哪一個小強了。這就好比在變量名前加上名字空間字首。是以可以通俗的說,名字空間就是一個變量的姓氏。問題是這樣我們還會碰到一個問題,世界上有很多姓張的,也有可能有很多的張小強,這怎麼辦呢?這時候我們可以這樣說"張老三家的小強",張是一個名字空間,張老三又是張下面的二級名字空間.
張.老三的家.小強 = 110
張.三豐的家.小強= 119
也許說的更糊塗,但大緻就這樣吧,我本來也就不是說明這個的。
據微軟稱,WMI的命名空間共有16個,不過不用擔心,我們常用的隻有兩個:
1、 root\cimv2 在這個命名空間裡包括了絕大多數與計算機、作業系統相關聯的類。
2、 root\default 管理系統資料庫的類
在使用中,我們用一個字元串表示命名空間,就像檔案路徑一樣。
四、常用的腳本對象庫
WMI腳本對象庫由24個對象組成,在腳本中心有一副腳本庫對象模型的圖,有興趣的朋友可以參考一下,作為入門,我們一般隻用到其中的四個對象,其繼承和層級關系如下:
SwbemLocator教本庫對象→SwbemServicesWMI服務對象→SwbemObjectSet類執行個體集合對象→SwbemObject類的執行個體
好了,現在讓我們來舉個例子,詳細說明一下這四個對象在腳本中的應用方法:
例一:用來檢索計算機上安裝的光驅:
strComputer = "."
Set objSWbemLocator = CreateObject("WbemScripting.SWbemLocator")
Set objSWbemServices = objSWbemLocator.ConnectServer
Set colItems = objSWbemServices.ExecQuery("Select * from Win32_CDROMDrive")
For Each objItem in colItems
WScript.Echo "CD光牒驅動器的類型: " & objItem.Caption
WScript.Echo "盤符是: " & objItem.Id
Next
例二:用來檢索CPU型号
Set objSWbemObjectSet = objSWbemServices.InstancesOf("Win32_Processor")
For Each objSWbemObject In objSWbemObjectSet
Wscript.echo "CPU的型号為:" & objSWbemObject.name
請注意,這兩個腳本雖然簡單,卻代表了WMI腳本設計中最普遍的東西,可以說是很典型的腳本。讓我們來仔細觀察一下這兩個腳本,讨論讨論一下腳本通路WMI的基本方法:我們可以看到整個腳本的執行過程基本相同:
①定義了SwbemLocator的執行個體;SwbemServices、SwbemObjectSet、SwbemObject對象;建立了SwbemLocator的執行個體;②通過SwbemLocator的ConnectServer方法連接配接到WMI,獲得SwbemServices的執行個體集合;③枚舉集合中的每個執行個體;④顯示各執行個體的一些屬性。
讓我們來詳細說明一下各行代碼的詳細含義,并請仔細回想我們第二部分WMI基本結構中談到的編寫WMI腳本的基本步驟:(注意:考慮到腳本的簡易,我們編寫的腳本一般隻在本地計算機進行檢索,我們隻介紹涉及本地的這一部分,涉及到通路遠端計算機的部分我們就省略了,其實随着計算機安全技術的發展,僅憑WMI通路遠端計算機的可行性是越來越小了)
1、連接配接到指定的CIM命名空間
要用WMI對象程式設計,必須首先建立WMI對象腳本庫的執行個體,連接配接到目标計算機的CIM命名空間。
方法一:
步驟一、建立SwbemLocator對象的執行個體。代碼為:
然後用SwbemLocator對象的ConnectServer方法(SwbemLocator對象隻有1個隻讀屬性Security_和1個方法ConnectServer)建立WMI服務的連接配接,傳回一個命名空間的連接配接(SwbemServices對象),代碼為:
Set objSWbemServices = objSWbemLocator.ConnectServer()
ConnectServer方法共有8個參數,所有參數都是可選的,其參數格式如下:
ConnectServer([strComputName],[strNamespace],[strUser],[strPassword],[strLocale],[strAuthority],[iSecurityFlags],[objwbemNamedValueSet])
考慮到WMI的複雜性,在使用中我們如果隻是在本地計算機上進行檢索和查詢,那麼我們隻需要設定第1、2個參數,其它參數都可以省略;如果想連接配接到遠端計算機,一般需要對前4個參數進行設定,我們也隻對此做個簡單的介紹。
strServer——計算機名,預設為本機,本機也可以用”.”
strNamespace——需要登入的CIM命名空間,例如:"root\CIMV2",預設為"root\CIMV2"。
方法二:用moniker名字法建立WMI服務的連接配接,這也是微軟推薦的連接配接方法
moniker名字法是利用GetObject函數直接建立WMI服務的連接配接,它的要點就是通過編寫一個moniker字元串作為GetObject函數的參數,然後傳回一個SwbemServices對象。
關于moniker字元串的完整格式如下:
"winmgmts:[{SecuritySettings}!][\\ComputerName][\Namespace][:ClassName][.KeyProperty='Value']"
"winmgmts:"是字首,
表示為WMI服務,必須使用;第二部分用來驗證權限和假冒級别的,省略。第三部分為計算機名字:"\\.\"是計算機名字,預設可省略,其餘同上;第四部分CIM命名空間:預設的命名空間為"root\CIMV2",預設可省略。
第五部分為類名。第六部分為屬性值。注意:當該moniker字元串不包括最後2項時(即為:"winmgmts:[\\ComputerName][\Namespace]"),則GetObject(moniker字元串)傳回的是一個命名空間的已驗證的連接配接(SwbemServices對象);當不包括最後1項時,傳回的是一個CIM類(SWbemObject對象);當包括最後2項時,傳回的是一個類的單獨執行個體(SWbemObject對象)。
2.獲得類的執行個體
我們有4種方法獲得類的執行個體,其中方法1和方法2是通過SwbemServices對象的InstancesOf方法和ExecQuery方法來獲得某個類的多個執行個體組成的集合對象。方法3和方法4則是傳回單獨的類的執行個體,即傳回的是一個SWbemObject對象。
1)InstancesOf方法獲得類的執行個體集合
InstancesOf方法的文法參數格式如下:
SwbemServices.InstancesOf(strClass)
strClass為類名,例如"Win32_Service"
回顧例二,就是用語句:Set objSWbemObjectSet = objSWbemServices.InstancesOf("Win32_Processor
") 來獲得"Win32 Processor "類的所有執行個體集合,然後我們可以用
……
語句獲得每一個類的執行個體SWbemObject對象,然後就可以根據我們的需要,進行相應的操作。
2)ExecQuery方法獲得類的執行個體集合
與InstancesOf方法不一樣的是,ExecQuery方法可以通過查詢語句,隻傳回比對部分執行個體和屬性。ExecQuery方法的文法參數格式如下:
SwbemServices.ExecQuery(strQuery)
strQuery為WMI查詢語言(WQL)構造的一個查詢語句字元串。
例如:
Set objSWbemObjectSet = objSWbemServices.ExecQuery("select ProcessorId from
Win32_Processor where DeviceID='cpu0'")
3)Get方法獲得一個類的執行個體(SWbemObject對象)
此方法也就不必再用 For Each objSWbemObject In objSWbemObjectSet :……:Next
語句從SWbemObjectSet對象中獲得每一個類的執行個體SWbemObject對象,Get方法的文法參數格式如下:
SwbemServices.Get([strObjectPath][.KeyProperty='Value'])
strObjectPath是類的名字
KeyProperty是主鍵屬性名
Value是指定的主鍵屬性值
這裡要注意的是如果要獲得一個類的執行個體,則strObjectPath.KeyProperty='Value'中的任何一項都不能省略,例如:
Set objSWbemServices = GetObject("winmgmts:")
Set objSWbemObject = objSWbemServices.Get("Win32_Processor.DeviceID='cpu0'")
Wscript.echo “CPU的型号為”:" & objSWbemObject.ProcessorId
看,結果一樣,腳本卻簡化了不少。
4)直接用moniker名字法獲得一個類的執行個體
在說明Moniker名字法的時候我們說過,當包括最後2項時,傳回的是一個類的單獨執行個體,如:Set objSWbemObject =
GetObject("winmgmts:Win32_Processor.DeviceID='cpu0'")
Wscript.echo "首枚CPU序列号:" & objSWbemObject.ProcessorId
是不是更加簡單?僅僅2條語句就獲得了CPU的序列号。
3.讀取類的執行個體屬性,調用類的方法
實在是太多了,你可以參照C:/WINDOWS/system32/wbem/cimwin32.mfl檔案中,對所有類的屬性和方法的描述。也可以用下列代碼查詢,雖然看起來有點困難,不過看的多了也就明白了。strClass=inputbox("請輸入你要查詢的類")
strNameSpace = "root\cimv2"
Const wbemFlagUseAmendedQualifiers = &h20000
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\" & strNameSpace)
Set objClass = objWMIService.Get(strClass, wbemFlagUseAmendedQualifiers)
strMOF = objClass.GetObjectText_
WScript.Echo strMOF
本文轉自hcy's workbench部落格園部落格,原文連結:http://www.cnblogs.com/alterhu/archive/2012/04/07/2435927.html,如需轉載請自行聯系原作者。