Is my device running on battery or AC power?

At times, it's helpful to know if the device running your application is plugged in or on battery power (long duration process, software update, etc).  Since the .NET Compact Framework does not provide a managed implementation for this check, you will need to P/Invoke to the native power status API.  The power status P/Invoke is straight forward and will provide a good deal of information about the battery - charge level, voltage, even battery chemistry.

Today's snippet uses the power status P/Invoke to check to see whether or not the device is connected to an AC power source (ACLineStatus).  For that field, I defined the three (3) power states listed in the Windows CE .NET SDK documentation into an enum.  This enum is interesting in that it's base type is specified as a byte, allowing it to fit neatly into the structure.

Since my little example does not use the remainder of the structure, please refer to the Windows CE .NET SDK documentation for details regarding their usage.  If your application is interested in the BatteryFlag, BackupBatteryFlag and/or BatteryChemistry elements, you may wish to implement enum(s) similar to what I did for ACLineStatus.

As with my other mini-snippets, I have written this one to use a MessageBox to display the results.

using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;

class AcPowerCheck
{
    public static void Main()
    {
        String msg = "Power status check failed.";
        PowerStatus info = new PowerStatus();      

        // query the device's power status
        Int32 result = GetSystemPowerStatus(ref info,
                                            Marshal.SizeOf(info),
                                            true);
        if(!result.Equals(0))
        {
            // common message portion
            msg = "Power source:";

            // a non-zero return from the native GetSystemPowerStatusEx
            //  API indicates success
            if(info.ACLineStatus.Equals(ACLineStatus.Online))
            {
                // plugged in
                msg = String.Format("{0} AC Power", msg);
            }
            else if(info.ACLineStatus.Equals(ACLineStatus.Offline))
            {
                // not plugged in
                msg = String.Format("{0} Battery", msg);
            }
            else
            {
                // could not be determined
                msg = String.Format("{0} Unknown", msg);
            }
        }
       
       
        // display the message
        MessageBox.Show(msg);
    }

    // p/invoke signature
    [DllImport("coredll.dll", EntryPoint="GetSystemPowerStatusEx2", SetLastError=true)]
    private extern static Int32 GetSystemPowerStatus(ref PowerStatus powerStatus,
                                                    Int32 length,
                                                    Boolean update);
}

// managed version of the SYSTEM_POWER_STATUS_EX2 structure
public struct PowerStatus
{
  public ACLineStatus ACLineStatus;
  public Byte BatteryFlag;
  public Byte BatteryLifePercent;
  public Byte Reserved1;
  public Int32 BatteryLifeTime;
  public Int32 BatteryFullLifeTime;
  public Byte Reserved2;
  public Byte BackupBatteryFlag;
  public Byte BackupBatteryLifePercent;
  public Byte Reserved3;
  public Int32 BackupBatteryLifeTime;
  public Int32 BackupBatteryFullLifeTime;
  public Int32 BatteryVoltage;
  public Int32 BatteryCurrent;
  public Int32 BatteryAverageCurrent;
  public Int32 BatteryAverageInterval;
  public Int32 BatterymAHourConsumed;
  public Int32 BatteryTemperature;
  public Int32 BackupBatteryVoltage;
  public Byte BatteryChemistry;
}

// enumeration containing the values for
//  SYSTEM_POWER_STATUS_EX2.ACLineStatus
public enum ACLineStatus : byte
{
    Offline = 0,
    Online  = 1,
    Unknown = 255,
}

To keep the P/Invoke easy for me to read, I have overridden the name.  For those who may not be familiar with P/Invokes, you can change the name used in managed code by specifying the actual native API name in the EntryPoint property in the DllImport attribute (as shown below).

[DllImport("coredll.dll", EntryPoint="GetSystemPowerStatusEx2", SetLastError=true)]
private extern static Int32 GetSystemPowerStatus(ref PowerStatus powerStatus,
                                                Int32 length,
                                                Boolean update);

I hope you find this mini-snippet useful.

Take care!
-- DK

Disclaimer(s):
This posting is provided "AS IS" with no warranties, and confers no rights.