Where does `powercfg` get battery health information, and why isn't it in WMI?
It looks like you have to dig into MSBattery super class:
A number of the classes in root\wmi return results from more than one class. That sounds odd but it can be explained by an example.
The namespace contains a number of classes related to the battery in laptops
gwmi -Namespace root\wmi -List *battery* MSBatteryClassEvent BatteryStatusChange BatteryTagChange MSBatteryClass BatteryStaticData BatteryRuntime BatteryCycleCount BatteryTemperature BatteryStatus BatteryFullChargedCapacity
We’ll ignore the event and change classes for now. If we pick out the MSBattery class we get information from a number of other classes returned – MSBattery is a super class.
PS> gwmi -Namespace root\wmi -Class MSBatteryClass | select __class __CLASS ——- BatteryCycleCount BatteryFullChargedCapacity BatteryStaticData BatteryRuntime BatteryStatus
Examples, that kind of work on my laptop:
Get-WmiObject -Namespace 'root\wmi' -Query 'select DeviceName, ManufactureName, Chemistry, DesignedCapacity from BatteryStaticData'
__GENUS : 2
__CLASS : BatteryStaticData
__SUPERCLASS :
__DYNASTY :
__RELPATH :
__PROPERTY_COUNT : 4
__DERIVATION : {}
__SERVER :
__NAMESPACE :
__PATH :
Chemistry : 1852787020
DesignedCapacity : 48400
DeviceName : K52F-44
ManufactureName : ASUSTek
PSComputerName :
Get-WmiObject -Namespace 'root\wmi' -Query 'select FullChargedCapacity from BatteryFullChargedCapacity'
__GENUS : 2
__CLASS : BatteryFullChargedCapacity
__SUPERCLASS :
__DYNASTY :
__RELPATH :
__PROPERTY_COUNT : 1
__DERIVATION : {}
__SERVER :
__NAMESPACE :
__PATH :
FullChargedCapacity : 47157
PSComputerName :
Get-WmiObject -Namespace 'root\wmi' -Query 'select CycleCount from BatteryCycleCount'
__GENUS : 2
__CLASS : BatteryCycleCount
__SUPERCLASS :
__DYNASTY :
__RELPATH :
__PROPERTY_COUNT : 1
__DERIVATION : {}
__SERVER :
__NAMESPACE :
__PATH :
CycleCount : 0
PSComputerName :
Why kind of? Because while you can see that DesignedCapacity
, FullChargedCapacity
and CycleCount
have some values, powercfg /batteryreport
doesnt recoginze them:
Here is a simple WMI "crawler" that combines all battery-classes into one object:
# get battery-identifier:
$batteryClass = Get-WmiObject -Namespace root\WMI -Class MSBatteryClass
if (!$batteryClass) {'this device has no physical battery.'; break}
$batteryData = foreach ($entry in $batteryClass) {
if ($entry.UniqueID) {$entry | select UniqueID, InstanceName}
}
# find data based on the UniqueID of the battery:
foreach ($entry in Get-wmiobject Win32_battery) {
$battery = @($batteryData).where{$_.UniqueID -eq $entry.DeviceID}
$attribs = $entry | Get-Member | ?{$_.MemberType -eq 'Property' -and !$_.name.startswith('__')}
foreach ($a in $attribs.name) {
$battery | Add-Member -Name "Win32_battery.$a" -Value $entry.$a -MemberType NoteProperty
}
}
# find data based on the InstanceName of the battery:
foreach ($class in $batteryClass.__CLASS | select -Unique) {
$classData = Get-WmiObject -Namespace root\WMI -Class $class
foreach ($entry in $classData) {
$battery = @($batteryData).where{$_.InstanceName -eq $entry.InstanceName}
$attribs = $entry | Get-Member | ?{$_.MemberType -eq 'Property' -and !$_.name.startswith('__')}
foreach ($a in $attribs.name) {
$battery | Add-Member -Name "$class.$a" -Value $entry.$a -MemberType NoteProperty
}
}
}
$battery
Unfortunaltely the WMI-classes do not translate all values into readable format (e.g. chemistry is just a value but not a string) and also not any runtime estimation for the fully charged battery. That one comes from the history of all charg/discharge events into the powercfg-report.