目錄
- 1. 使用Windows Form的PowerStatus
- 2. 使用WMI
- 3. 使用Windows Vista新增的本地API
返回目錄
1. 使用Windows Form的PowerStatus
第一種最原生態的方法是使用Windows Forms中的SystemInformation類型的PowerStatus屬性,返回一個PowerStatus類型的對象。
可以通過BatteryChargeStatus屬性來獲得電池狀態,同時Power類型還包含其他屬性比如BatteryLifePercent能夠擷取詳細的電量資訊。不過使用這種方法唯一的缺點是沒有任何電池狀態改變的事件通知機制,也就是說需要開發人員主動去調用。
返回目錄
2. 使用WMI
優點 |
有不太完美事件通知能力,不需要引用Windows Form架構。 |
缺點 |
事件通知效率不高,需要引用System.Management.dll。 |
另一個方法就是WMI,去查詢Win32_Battery類型的Battery_Status屬性。類似下面的WQL語句:
SELECT BatteryStatus FROM Win32_Battery
當然,如果就是這樣的話, 那麼和第一種方法沒什麼區別。
因此我們可以使用WMI的事件查詢,這樣當電池狀態發生變化後,我們可以第一時間得到資訊。
針對WMI,這裡就不講理論內容了,讀者可以參考網路或者我部落格的其他WMI文章。我們這裡直接上代碼,通過“__InstanceModificationEvent”這個WMI事件類型來指定對象修改後的事件通知,然後查詢Win32_Battery類型的屬性,代碼:
//注意:引用System.Management.dll 和 using System.Management;
static void Main(string[] args)
{
//建立WQL事件查詢,用於執行個體建立
var qCreate = new WqlEventQuery("__InstanceModificationEvent",
TimeSpan.FromSeconds(3), //WHTHIN = 1
"TargetInstance ISA 'Win32_Battery'");
//建立事件查詢的接聽程式(ManagementEventWatcher)
var wCreate = new ManagementEventWatcher(qCreate);
//事件註冊代碼
wCreate.EventArrived += (sender, e) =>
{
Console.WriteLine("運行:{0}", GetInfo(e.NewEvent));
};
//非同步開始偵聽
wCreate.Start();
Console.WriteLine("按任意鍵停止監控");
System.Threading.Thread.Sleep(-1);
}
//輸出事件對應的ManagementBaseObject(本例中的Win32_Battery執行個體)的資訊
static int GetInfo(ManagementBaseObject mobj)
{
var instance = (ManagementBaseObject)mobj["TargetInstance"];
var prop = instance.Properties["BatteryStatus"];
return (ushort)prop.Value;
}
程式會直接輸出BatteryStatus的狀態代碼,具體指的意義可以參考MSDN關於Win32_Battery WMI類型的文檔。運行效果如下:
(上面程式運行時會出現連續輸出同一個值的情況,可能是Win32_Battery的其他屬性發生變化。因為WMI事件查詢InstanceModificationEvent是針對一個類型的,而我們只輸出其中的BatteryStatus屬性)
但是貌似Win32_Battery類型不是原生態的WMI事件類型(參考這篇文章:http://blogs.msdn.com/b/wmi/archive/2009/12/28/using-within-in-a-wmi-event-query.aspx)。那麼實際上事件的通知是根據WQL事件查詢中的WITHIN時間值來完成的。顯然WITHIN越高,準確度越高,但是更消耗資源。那麼,這種事件通知不完美。
返回目錄
3. 使用Windows Vista新增的本地API
優點 |
具備事件通知能力 |
缺點 |
要求Windows Vista版本以上的系統,需要調用本地API或者引用Windows API Code Pack |
最後一種方法從功能上講是最完美的,當然代價是要求Windows Vista版本以上的系統,需要調用本地API或者引用Windows API Code Pack。因為從Windows Vista開始,Windows提供相互關聯類型的API來通知使用者電源狀態的變化。
這裡我們就通過引用Windows API Code Pack來便於使用C#完成上述需求。在Microsoft.WindowsAPICodePack.ApplicationServices命名空間內,使用PowerManager類型可以完成需求,PowerManager類型的成員如下:
使用BatteryLifePercentChanged事件就可以知道電池狀態變化。通過GetCurrentBatteryState方法來擷取具體的電池資訊。
當然PowerManager類型還提供其他電源電池相關的功能支援,讀者可以自行參考下Windows API Code Pack的文檔。