I was working with a customer last week who needed to get the battery charge remaining percent for two batteries. How hard could that be? I did a quick search and found that GetSystemPowerStatus() returns the charge remaining for one battery. Which is, well, useless for a multi-battery system. Some more searching turned up the Windows Management Instrumentation (WMI) which can be used to get information about multiple batteries, and the adventure was on.
 
I created a class that I call Win32_Battery and started by getting the battery data:
 
        ManagementObjectCollection Batteries;
       
        public Win32_Battery()
        {
            Refresh();
        }
        public void Refresh()
        {
            try
            {
                SelectQuery msQuery = new SelectQuery("SELECT * FROM Win32_Battery");
                ManagementObjectSearcher searchProcedure = new ManagementObjectSearcher(msQuery);
                Batteries = searchProcedure.Get();
            }
            catch (SystemException)
            {
                System.Windows.Forms.MessageBox.Show("Error getting battery information");
            }
        }
 
The goal of this class it to allow an application to get a snapshot of the battery information, and then query it through separate functions to get the pieces of data as they are needed. With that in mind, the Refresh method gets the snapshot of data and stores it in Batteries, and ManagementObjectCollection. Each object in Batteries represents information about one of the batteries in the system.
Refresh() sets up a search for all properties available in the WMI Win32_Battery class, then searches to get the information and stores it in Batteries for use in the methods below.
The next method that I added is NumberOfBatteries() which returns the number of objects in the Batteries collection:
        public int NumberOfBatteries()
        {
            int BatteryCount = 0;
            try
            {
                BatteryCount = Batteries.Count;
            }
            catch (SystemException)
            {
            }
            return BatteryCount;
        }
 
And finally, I added a method to get the percent charge remaining for a battery, GetPercentChargeRemaining(). The work for GetPercentChargeRemaining() is performed by a helper function called GetBatteryProperty() which does the real work of getting the value for a WIN32_BATTERY object.
        UInt16 GetBatteryProperty(int BatteryNumber, String Property)
        {
            int BatteryIndex = 0;
            UInt16 ReturnVal = 0;
            try
            {
                foreach (ManagementObject item in Batteries)
                {
                    if (BatteryIndex == BatteryNumber)
                    {
                        try { ReturnVal = (UInt16)item[Property]; }
                        catch (SystemException)
                        {
                        }
                    }
                    BatteryIndex++;
                }
            }
            catch (SystemException)
            {
                Console.WriteLine("Get Properties failed");
            }
            return ReturnVal;
        }
        public int GetPercentChargeRemaining(int BatteryNumber)
        {           
            return GetBatteryProperty( BatteryNumber, "EstimatedChargeRemaining" );
        }
 
This code demonstrates how to get data from WMI, and could be easily modified for use with other WMI classes.
 
Copyright © 2010 – Bruce Eitman
All Rights Reserved