.NET(C#):关于获取系统电池状态

来源:互联网 发布:吾生有涯而知无涯解析 编辑:程序博客网 时间:2024/04/29 17:10

目录

  • 1. 使用Windows Form的PowerStatus
  • 2. 使用WMI
  • 3. 使用Windows Vista新增的本地API

 

返回目录

1. 使用Windows Form的PowerStatus

优点 .NET原生态 缺点 没有事件通知

第一种最原生态的方法是使用Windows Forms中的SystemInformation类型的PowerStatus属性,返回一个PowerStatus类型的对象。

image

可以通过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类型的文档。运行效果如下:

image

(上面程序运行时会出现连续输出同一个值的情况,可能是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类型的成员如下:

image

使用BatteryLifePercentChanged事件就可以知道电池状态变化。通过GetCurrentBatteryState方法来获取具体的电池信息。

当然PowerManager类型还提供其他电源电池相关的功能支持,读者可以自行参考下Windows API Code Pack的文档。


<script type="text/javascript"><!--google_ad_client = "ca-pub-1944176156128447";/* cnblogs 首页横幅 */google_ad_slot = "5419468456";google_ad_width = 728;google_ad_height = 90;//--></script><script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>