WMI 101

更新日期: 2006 年 3 月 15 日

作者: 賴榮樞
http://www.goodman-lai.idv.tw

WMI(Windows Management Instrumentation)是微軟根據DMTF(Distributed Management Task Force)所制訂的Web-based Enterprise Management(WBEM)為基礎的實作。話說眾多的系統、周邊、網路、通訊等軟硬體大廠為了讓系統管理人員便於管理大型的企業網路,便聯合組成DMTF,希望透過DMTF制訂出讓大廠共同遵守的規格,進而簡化資訊產品之間的溝通與聯繫。

因此,WBEM便是DMTF所制訂的規格,而各個大廠便再根據這項共通的規格,各自實作自己的管理介面、甚至管理工具。而WMI便是微軟根據DMTF/WBEM的實作;或者也可以說,WMI是微軟視窗版的WBEM;WBEM是根據DMTF的CIM(Common Information Model)所制訂,而CIM是一種Modeling Language。

微軟「正式」將WMI導入視窗作業系統是Windows 2000,Windows XP和Windows Server 2003當然也支援WMI。除了微軟、除了視窗作業系統之外,還有許多微軟的產品、還有許多廠商也都支援WBEM。例如微軟的Exchange 2000和System Management Server也支援WMI,而其他如英特爾、Computer Associates、昇陽、IBM、HP等公司也已經開始實作自己的WBEM,並且用在自身的資訊產品。

本頁內容

WMI的目的
執行WMI的需求
WMI的架構
簡單的WMI類別應用實例
WMI類別
WMI Provider
參考資料

WMI的目的

就實用或使用的角度而言,WMI其實是一組龐大的物件模組(Object Model),透過這組物件模組,程式設計師可以掌控整個Windows系統的軟硬體資源,包括目前登入的使用者、執行中的行程(process)或服務(service)、連線的印表機、磁碟空間等等。

簡而言之,WMI將程式設計師/系統管理者與作業系統資源隔開,如果程式設計師想要開發Windows系統管理程式(例如使用C++語言),或者是系統管理者想要利用如VBScript、或JavaScript等描述語言(Scripting Language)自行撰寫系統管理的小程式,都可以直接利用WMI所提供的類別來完成,而不需另行透過Win32 API或其他的程式庫。

另外,所謂「作業系統資源」所包含的層面相當廣泛,如前所述:目前登入系統的使用者、執行中的行程(process)或服務(service)、連線的印表機、磁碟空間等等,都是作業系統資源的一部份。如果WMI真的要成為系統管理者的神兵利器,那麼WMI的物件模組就必須讓程式設計師或系統管理者可以存取整個Windows作業系統上的所有軟硬體資源。

因此WMI類別能否將作業系統資源完整地提供給程式設計師或系統管理者,便成為WMI能否得到青睞的關鍵。這使得DMTF的WBEM規格成為這部分的關鍵:因為WBEM是廠商之間的共通規格,因此只要廠商依循WBEM,就不會有問題;如果不願遵守WBEM,前述的理想目標也就不可能實現。

另外,由於WMI已經完全考慮到遠端遙控、網路處理的狀況,因此系統管理者可以輕易地利用WMI物件模組並透過網路來管理遠端的Windows伺服器。

執行WMI的需求

Windows Server 2003、Windows XP、Windows 2000和Windows Me等作業系統已經內建支援WMI,而版本較舊的Windows 95/98/NT 4.0,也可以到微軟網站下載、安裝免費的WMI CORE(目前是1.5版),讓系統支援WMI。微軟網站有兩種不同形式的WMI CORE:Windows Management Instrumentation (WMI) CORE 1.5 (Windows 95/98)是Windows 9x專屬,而Windows Management Instrumentation (WMI) CORE 1.5 (Windows NT 4.0)則適用於Windows NT 4;此外,微軟也提供了WMI CORE 1.5 SDK(下載網址請參考文末的參考資料)。

另外,WMI的管理功能是由WMI Provider所提供,因此也應該留意整個環境是否具備適當的WMI Provider。例如若想使用SNMP Provider的功能,就需安裝SNMP Provider,而有些WMI Provider是另外放在Windows安裝光碟的資料夾,通常會在VALUEADD\MSFT\MGMT資料夾底下。

WMI的架構

WMI是希望能提供一致的介面,讓本機或遠端的程式(包括script)能獲取電腦或網路系統的管理資料,也因為有了WMI,只要以Visual Basic、C/C++以及.NET、ActiveX Scripting所支援的語言,就可以叫用WMI所提供的介面;甚至也可以SQL語言透過ODBC存取WMI所提供的管理資料。

圖 1 WMI架構圖
圖 1 WMI架構圖

圖 1是WMI架構圖,以下簡述其中的重要部分。

  • Managed objects and providers:
    這個部分位於最底層,其中包含了WMI Provider以及被WMI管理的物件。WMI之所以能發揮作用,全都是因為WMI Provider提供了相關的必要資訊,因此系統廠商如果要讓他們的產品可以透過WMI加以存取、控制,就必須為他們的產品提供WMI provider(如果您想開發自己產品的WMI Provider,WMI SDK是不可或缺的資料,而這份SDK包含在Windows Platform SDK之內)。被WMI管理的物件可能是Windows作業系統的行程、服務,或者是安裝在Windows的硬體周邊設備。不論是Windows系統上的軟體或硬體資源,都必須透過各自的WMI Provider,將相關的資訊或規格提供給WMI Object Model,以便程式設計師或系統管理者藉以掌控。

  • WMI infrastructure:
    中間這一層是上、下兩層以及WMI repository相互運作的媒介,其中包含了撰寫程式需要叫用的WMI類別,例如自己寫的管理程式若要處理WMI provider提供的資訊,就要透過這一層的協助。WMI repository只儲存了provider所定義的類別靜態資料,大部分的資料都是由管理程式要求時,即時向provider索取。

  • WMI management applications and scripts:
    這一層就是會利用WMI的管理程式,只要以Visual Basic、C/C++以及.NET、ActiveX Scripting所支援的語言,就可以叫用WMI所提供的介面(也就是中間層);甚至也可以SQL語言透過ODBC存取WMI所提供的管理資料。

簡單的WMI類別應用實例

WMI提供了一組龐大的類別物件模組,對系統管理者來說,透過Windows系統的WSH來使用WMI類別,將可以完成許多日常性的系統管理工作。以下筆者便以WSH搭配VBScript,再透過WMI類別列出目前系統執行中的所有行程,作為使用WMI類別的簡單實例。

LstProcessOne.vbs
' LstProcessOne.vbs By Goodman Lai
' 以下是利用 WMI 物件模組列出目前所有執行中的行程,
' 並且利用 Internet Explorer 顯示所有的行程
' By Goodman Lai
' 利用 IE 顯示執行結果;先建立 IE instance
Set oIE = CreateObject("InternetExplorer.Application")
oIE.Navigate "about:blank"
Set oIEDoc = oIE.Document
With oIE
  .AddressBar = False
  .StatusBar = False
  .ToolBar = False
  .MenuBar = False
  .Visible = True
  .Width = 500
  .Height = 700
  .Left = 50
  .Top = 20
End With

' Now edit the HTML codes to IE
oIEDoc.WriteLn "<html>"
oIEDoc.WriteLn "<head>"
oIEDoc.WriteLn "<title>LstProcessOne.vbs: 列出目前所有執行中的行程</title>"
oIEDoc.WriteLn "</head>"
oIEDoc.WriteLn "<body>"
oIEDoc.WriteLn "以下是利用 WMI 物件模組列出目前所有執行中的行程"
oIEDoc.WriteLn "<table border='1' width='100%'>"
oIEDoc.WriteLn "<tr>"
oIEDoc.WriteLn "<td width='35%'>Process Handle</td>"
oIEDoc.WriteLn "<td>Process Name</td>"
oIEDoc.WriteLn "</tr>"

' 透過 WMI 物件模組列出目前所有執行中的行程
set oLocator = CreateObject ("WbemScripting.SWbemLocator")
set oService = oLocator.ConnectServer()
for each oProcess in oService.InstancesOf("Win32_Process")
    oIEDoc.WriteLn "<tr>"
    oIEDoc.WriteLn "<td>" & oProcess.Handle & "</td>"
    oIEDoc.WriteLn "<td>" & oProcess.Name & "</td>"
    oIEDoc.WriteLn "</tr>"
next

' edit the ending  of HTML codes to IE
oIEDoc.WriteLn "</table>"
oIEDoc.WriteLn "</body>"
oIEDoc.WriteLn "</html>"

' 清除所有使用過的物件變數
set oProcess = nothing
set oService = nothing
set oLocator = nothing
set oIEDoc = nothing
set oIE = nothing
' 程式到此結束
			

這個名為LstProcessOne.vbs的程式會透過WMI類別,列出目前所有執行中的行程代碼(Handle)和名稱,並且利用Internet Explorer來顯示這些行程的資訊(圖 2即為執行結果)。程式雖然有五十多行,不過其中大多在處理利用Internet Explorer顯示資訊,真正與WMI相關的程式碼僅有加粗顯示的八行而已(在筆者的測試過程中發現,執行LstProcessOne.vbs或LstProcessTwo.vbs程式的時候,偶爾會出現莫名的錯誤訊息以致程式無法執行。如果您也遇到這種狀況,請試著多執行幾次)。

就像所有叫用類別的程式,一開始都得先利用CreateObject函數建立實體(instance),接著再一一地取得後續的類別實體,進而再透過類別的方法或屬性得到我們預期的結果。如果想要利用WMI類別列出所有執行中的行程,可以利用其中的SwbemServices類別,透過這個類別的Win32_Process子類別,我們便可以得到包含所有行程的集合物件。而要得到SwbemServices類別,我們則必須先以SwbemLocator類別的ConnectServer方法連上要列出行程的電腦。

圖 2 LstProcessOne.vbs的執行結果
圖 2 LstProcessOne.vbs的執行結果

所以下列的程式碼可以讓我們得到SwbemLocator類別:

set oLocator = CreateObject ("WbemScripting.SWbemLocator")
			

因為要列出行程的是本機電腦,而且目前筆者是以管理者的身份登入系統,因此可以省略ConnectServer方法的所有參數:

set oService = oLocator.ConnectServer()
			

oService.InstancesOf("Win32_Process")將會傳回包含所有執行中形成的集合物件,因此便可利用for-each處理集合物件中的所有行程:

for each oProcess in oService.InstancesOf("Win32_Process")
			

下列程式碼會將行程的代碼顯示在Internet Explorer:

oIEDoc.WriteLn "<td>" & oProcess.Handle & "</td>"
			

而下列程式碼會將行程的名稱顯示在Internet Explorer:

oIEDoc.WriteLn "<td>" & oProcess.Name & "</td>"
			

除了上述的呼叫方式之外,下列的程式也可以達到相同的結果:

LstProcessTwo.vbs
' LstProcessTwo.vbs By Goodman Lai
' 以下是利用 WMI 物件模組列出目前所有執行中的行程,
' 並且利用 Internet Explorer 顯示所有的行程
' 利用 IE 顯示執行結果;先建立 IE instance
Set oIE = CreateObject("InternetExplorer.Application")
oIE.Navigate "about:blank"
Set oIEDoc = oIE.Document
With oIE
  .AddressBar = False
  .StatusBar = False
  .ToolBar = False
  .MenuBar = False
  .Visible = True
  .Width = 500
  .Height = 700
  .Left = 50
  .Top = 20
End With

' Now edit the HTML codes to IE
oIEDoc.WriteLn "<html>"
oIEDoc.WriteLn "<head>"
oIEDoc.WriteLn "<title>LstProcessTwo.vbs: 列出目前所有執行中的行程</title>"
oIEDoc.WriteLn "</head>"
oIEDoc.WriteLn "<body>"
oIEDoc.WriteLn "以下是利用 WMI 物件模組列出目前所有執行中的行程"
oIEDoc.WriteLn "<table border='1' width='100%'>"
oIEDoc.WriteLn "<tr>"
oIEDoc.WriteLn "<td width='35%'>Process Handle</td>"
oIEDoc.WriteLn "<td>Process Name</td>"
oIEDoc.WriteLn "</tr>"

' 透過 WMI 物件模組列出目前所有執行中的行程
for each oProcess in GetObject("winmgmts:").InstancesOf("Win32_Process")
    oIEDoc.WriteLn "<tr>"
    oIEDoc.WriteLn "<td>" & oProcess.Handle & "</td>"
    oIEDoc.WriteLn "<td>" & oProcess.Name & "</td>"
    oIEDoc.WriteLn "</tr>"
next

' edit the ending  of HTML codes to IE
oIEDoc.WriteLn "</table>"
oIEDoc.WriteLn "</body>"
oIEDoc.WriteLn "</html>"

' 清除所有使用過的物件變數
set oProcess = nothing
set oIEDoc = nothing
set oIE = nothing
' 程式到此結束
			

在上述這個名為LstProcessTwo.vbs的程式當中,筆者使用另一種呼叫WMI物件模組的方式,也能達到與LstProcessOne.vbs相同的結果。請您注意程式中的粗體部分:

for each oProcess in GetObject("winmgmts:").InstancesOf("Win32_Process")
			

我們也可以利用GetObject("winmgmts:")方式連上本機電腦,這會傳回SwbemServices類別;也就是說GetObject("winmgmts:")就相當於以下兩行程式:

set oLocator = CreateObject ("WbemScripting.SWbemLocator")
set oService = oLocator.ConnectServer()
			

WMI類別

行文至此,相信您也發現:要利用WMI管理Windows系統,熟悉WMI類別是相當重要的。以下筆者將簡述WMI類別,而詳細的類別內容,則可參考文後所列的參考資料。

  • Win32類別:這是處理Windows作業系統最重要的類別。

  • WMI Registry類別:用來編修、新增、刪除Windows登錄資料庫機碼和鍵值的類別。

  • WMI System類別:包含在WMI Core(圖 1第2層)每個命名空間的預定類別,只要是以兩個底線字元開頭的名稱,就是這種類別,而這些類別提供為WMI提供了許多基本功能(舉例而言,WMI系統類別類似SQL Server的系統資料表)。

  • WMI System屬性:這些屬性主要是用在WMI的內部運作,如同WMI System Classes,這些屬性的名稱也是以兩個底線字元開頭。

  • MSFT類別:由微軟提供的其他處理作業系統功能的類別。

  • CIM類別:如果想要自行開發WMI類別,就可以從這裡繼承類別。Win32類別就從這裡繼承。

  • Standard Consumer類別:一組會觸發特定收到事件的WMI事件消費者。

  • MSMCA類別:處理系統事件的類別。

  • WMI C++類別:WMI C++ Provider Framework類別,但微軟已經不建議使用。

WMI Provider

之前提過WMI物件模組之所以得以發揮作用,全都是因為WMI Provider提供了相關的必要資訊,因此系統廠商如果要讓他們的產品可以透過WMI物件模組加以存取、控制,就必須為他們的產品提供WMI Provider。在本文最後,筆者將簡述Windows內建或常見的WMI Provider,完整、詳細的說明,則可參考文後所列的參考資料。。

  • Active Directory Provider:顧名思義,Active Directory Provider提供了存取AD服務的功能。無法用在Windows NT和Windows Me/98/95。

  • BizTalk Provider:能存取BizTalk管理物件。

  • Distributed File System (DFS) Provider:提供分散式檔案系統的管理功能。無法用在Windows 2000/NT和Windows XP。

  • DNS Provider:提供Domain Name System的管理功能。無法用於Windows 2000 Professional、Windows XP和Windows Me/98/95。

  • Disk Quota Provider:提供NTFS磁碟配額的管理功能。無法用於Windows 2000/NT。

  • Event Log Provider:Event Log Provider提供了記錄系統事件的相關功能;它可以讓您讀取系統所記錄的事件、調整事件記錄選項,也可以掌控事件記錄的備份狀況。

  • Internet Information Services (IIS):提供查詢、調整IIS metabase的程式設計介面。

  • IP Route Provider:提供網路路由資訊。無法用於Windows 2000/NT。

  • Job Object Provider:能存取命名核心工作物件裡的資料。無法用於Windows 2000以及Windows Me/98/95。

  • Performance Counter Provider:Performance Counter Provider讓WMI物件模組具備瞭解系統效能的功能。

  • Power Management Event Provider:提供電源管理的事件資訊。無法用於Windows NT以及Windows Me/98/95。

  • Reporting Services Provider:定義了一組能讓程式叫用的WMI類別,程式可藉以修改報表伺服器和報表管理員的設定。無法用於Windows NT和Windows Me/98/95。

  • Security Provider:取得或更改能控制檔案、資料夾的擁有者、稽核、存取權限的安全設定。無法用於Windows Me/98/95。

  • Server Cluster Provider:定義了一組能用來存取叢集物件、屬性、事件的WMI類別。

  • Session Provider:能管理網路會期及連線。無法用於Windows NT以及Windows Me/98/95。

  • SNMP Provider:SNMP(Simple Network Management Protocol)是網路管理的業界標準,而SNMP Provider則讓WMI物件模組具備SNMP的網管功能。

  • System Registry Provider:能讓管理程式取得、修改系統登錄資料庫的資料,並且也能在系統登錄資料庫內容也所變動時收到通知;如果是64位元平台,就會有32位元和64位元等兩種版本的System Registry Provider。

  • WDM Provider:WDM(Windows Driver Model)是Windows 2000、Windows XP、Windows Server 2003所採用的硬體驅動程式規格,因此您應該不難猜到WDM Provider的作用。諸如輸入裝置、儲存設備、網路介面、通訊埠等裝置的相關資訊,皆由WDM Provider所負責。

  • Win32 Provider:Win32 Provider提供了相當核心、也相當基本的Windows系統管理功能,舉凡作業系統、周邊裝置、檔案系統等等的功能,都是由Win32 Provider所提供。例如之前列出所有執行中的行程範例,也是透過Win32 Provider而完成。

  • Windows Installer Provider:Windows Installer是微軟新制訂的視窗安裝程式設計規格,而這組Provider則可以讓WMI物件模組掌控系統內的程式安裝狀況—當然,程式必須是以Windows Installer規格,才能被監控。

  • Windows Product Activation Provider:提供Windows產品啟動(Windows Product Activation,WPA)的管理功能。

參考資料

顯示: