WMI事件概述
對於從事Winows編程的開發人員來說,事件驅動的應用程序設計是再熟悉不過了,但是WMI中的事件又是一個什麼樣的概念呢?對於寶貴的內存和CPU資源,管理員需要不斷的監視其性能;對於磁盤而言,我們需要隨時知道它的使用情況,包括I/O性能,剩余空間等……操作系統中如此之多的管理對象需要管理員一刻不停的監視其運行的狀態,這樣的工作負擔是十分龐大的。因此,能不能當管理對象的性能數據接近某個我們事先設定的臨界值時,發出警報或者Email通知給管理員,希望他能來處理。這種情形就是WMI中的事件處理機制,這種機制使得開發人員能夠發布、訂閱、傳遞事件的消息。
對於WMI事件處理機制來說,它必須解決三個方面的問題:
n 事件發布:能夠找到事件的源;
n 事件訂閱:能夠訂閱我感興趣的事件;
n 事件傳送:保證事件准確無誤的傳遞到事件訂閱者。
所幸的是WMI架構規范定義了完善的、強大的事件處理框架,使得上面的問題輕松的解決。您可以在編程時給出一個事件查詢,來過濾數據,獲取您感興趣的事件。
WMI事件分為三類:
n 內部事件:當類實例被創建、修改、刪除時,WMI響應這些內部的數據變化,這些信息來自CIM儲存庫。
n 外部事件:這類事件是用戶自定義的事件。
n 計時器事件:這種事件是在特定的事件或者每個指定的事件發生的事件,它是由計時器來發布的,並且是訂閱的用戶自己建立的計時器。
WMI事件查詢
WMI事件查詢語句與關系數據庫的SQL查詢語句很相似,下面給出一例:
SELECT *
FROM __InstanceModificationEvent
WITHIN 10
WHERE TargetInstance isa 'Win32_Service' AND
TargetInstance.StartMode = 'Manual' AND
TargetInstance.Started = FALSE AND
PreviousInstance.Started = TRUE
上面的例子查詢的事件條件(WHERE字句):事件源為Win32_Service(即windows服務)中的服務,服務啟動的模式為手動,而且是剛被停止的服務事件;WITHIN字句指定事件輪詢間隔為10秒鐘;FROM子句指定事件類型,即為實例被修改,包括服務啟動、暫停、終止等。(有關更加詳細的信息請參考WMI SDK文檔)
Microsoft公司新發布的Visual Studio 2003增強了服務器資源管理器的功能,對於WMI來說,我們可以通過服務器資源管理器查看管理類和管理事件,並且能夠做事件查詢,簡化了編程前WMI查詢的測試,也可以將這些管理對象做拖放到設計器,簡化了編程。為了使您的服務器資源管理器能夠增建WMI的功能,您需要到Microsoft公司的官方網站下載最新的WMI Extensions for Visual Studio Windows Server 2003 Explorer,並將其安裝。
安裝好了WMI Extensions後,展開服務器資源管理器您就可以看到Management Classes和Management Events兩個節點。通過WMI Extensions,您可以輕松的完成下列任務:
n 查詢WMI類的命名空間。您只需要右鍵單擊Management Classes,選擇Add Classes,在Find class containg文本框輸入類名,然後查找就可以找到這個類所在的命名空間;
n 編譯您的WMI查詢語句,從而獲取您感興趣的事件數據。右鍵單擊Management Events,選擇Add Event Query即打開了編譯WMI查詢語句的窗口,在輸入框中輸入查詢語句,並且選擇事件源的類型,就可以執行WMI查詢語句。這裡還有一個高級選項,自動生成查詢語句,查詢的結果在Visual Studio的輸出窗口中。
編程實現事件預定和處理
在這裡我們將看到兩個事件預定與處理的例子,一個是關於Win32_Service的事件預定與處理,一個是關於計時器事件的預定與處理,前者是同步的,後者是異步的。在給出例程之前,我們先看看有關事件預定與處理會涉及到的幾個類,它們均位於System.Management命名空間下。
WqlEventQuery類:它代表的是一個WMI事件查詢,它的構造函數有8個,用戶不同的情況。我們將只介紹其中的兩個構造函數。
public WqlEventQuery(string):輸入參數為WMI的SQL查詢語句,如給出的查詢語句:
SELECT *
FROM __InstanceModificationEvent
WITHIN 10
WHERE TargetInstance isa 'Win32_Service'
public WqlEventQuery(string, TimeSpan, string):輸入參數依次為事件類型,輪詢間隔,過濾條件。對應上面的WMI查詢語句,三個輸入參數分別為:”__InstanceModificationEvent”、 new TimeSpan(0,0,10)、” TargetInstance isa 'Win32_Service'”。上述的兩種方式使用構造函數得到的實例是一樣的。
ManagementEventWatcher類:根據指定的事件查詢預訂臨時事件通知,指定的事件指的是WqlEventQuery類的實例。ManagementEventWatcher的構造函數常使用的是帶一個WqlEventQuery對象的輸入參數。它還有另外一個重要的方法WaitForNextEvent()方法,用於等待下一個與指定查詢匹配的事件,然後返回該事件。Start()方法用於啟動查詢並等待事件通知(發生),Stop()方法停止預定事件通知。
有了這些准備後,我們可以看看程序了。
*****************************************************
//同步的事件預定和處理
public static void syncEvent()
{
//創建事件查詢,每隔一秒輪詢一次
string Query="SELECT * FROM __InstanceModificationEvent WITHIN 1 WHERE TargetInstance isa 'Win32_Service' AND TargetInstance.StartMode = 'Manual' AND TargetInstance.Started = FALSE AND PreviousInstance.Started = TRUE";
WqlEventQuery query=new WqlEventQuery(Query);
ManagementEventWatcher watcher=new ManagementEventWatcher(query);
// 直到下一次事件發生
ManagementBaseObject e = watcher.WaitForNextEvent();
//顯示返回事件的信息
Console.WriteLine(
"服務{0}剛被停止, 現在的狀態為: {1},服務描述為: {2}",
((ManagementBaseObject)e["TargetInstance"])["Name"], ((ManagementBaseObject)e["TargetInstance"])["State"],((ManagementBaseObject)e["TargetInstance"])["Description"]);