Где `powercfg` получает информацию о состоянии батареи и почему ее нет в WMI?

На Windows 10 (среди других версий), работающей на устройстве с аккумулятором, я могу использовать powercfg /batteryreport получить "Расчетную емкость" и "Емкость последней полной зарядки" для батареи, которые дают представление об оставшемся полезном сроке службы батареи и о том, насколько ее емкость снизилась в результате использования.

C:\Users\superuser\AppData\Local\Temp>powercfg /batteryreport
Battery life report saved to C:\Users\superuser\AppData\Local\Temp\battery-report.html

HTML-отчет генерируется мгновенно и отображает, помимо прочего, интересующую меня статистику:

Более того, я могу загрузить встроенную диагностическую среду этого ноутбука, и она отображает похожие цифры и количество циклов разрядки батареи.

Откуда эти значения получены? Я хотел бы иметь возможность отслеживать эти данные о времени автономной работы для парка ноутбуков, предпочтительно по сценарию Powershell. Казалось вероятным, что эти данные должны быть в WMI, и, конечно же, есть класс Win32_Battery, имеющий DesignCapacity а также FullChargeCapacity поля, но во всех протестированных мной системах они не определены:

PS C:\Users\superuser> Get-WmiObject -Class Win32_Battery | Select-Object -Property *Capacity | Format-List


DesignCapacity     :
FullChargeCapacity :

Должен быть какой-то программный способ доступа к этой информации, потому что powercfg делает это Если для этого есть какой-нибудь способ WMI, .NET или Powershell, я бы хотел узнать об этом. Я мог бы генерировать powercfg сообщать, а затем анализировать его, но я действительно не хочу применять уродливый обходной путь, когда, скорее всего, существует "правильный" способ сделать это, который просто ускользает от меня.

2 ответа

Решение

Похоже, вам нужно копаться в суперклассе MSBattery :

Ряд классов в корне \ wmi возвращает результаты более чем одного класса. Это звучит странно, но это можно объяснить на примере.

Пространство имен содержит ряд классов, связанных с батареей в ноутбуках

gwmi -Namespace root\wmi -List *battery*

MSBatteryClassEvent
BatteryStatusChange
BatteryTagChange 
MSBatteryClass
BatteryStaticData
BatteryRuntime
BatteryCycleCount 
BatteryTemperature
BatteryStatus
BatteryFullChargedCapacity

Мы пока проигнорируем событие и изменим классы. Если мы выберем класс MSBattery, мы получим информацию из ряда других возвращенных классов - MSBattery - это суперкласс.

PS> gwmi -Namespace root\wmi -Class MSBatteryClass | select __class

__CLASS  ——-
BatteryCycleCount
BatteryFullChargedCapacity
BatteryStaticData
BatteryRuntime BatteryStatus

Примеры такой работы на моем ноутбуке:

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   : 

Почему вроде? Потому что пока вы можете видеть, что DesignedCapacity , FullChargedCapacity а также CycleCount иметь некоторые значения, powercfg /batteryreport не распознает их:

Вот простой «сканер» WMI, который объединяет все классы батарей в один объект:

      # 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

К сожалению, классы WMI не переводят все значения в читаемый формат (например, химический состав — это просто значение, а не строка), а также не дают никакой оценки времени работы полностью заряженной батареи. Это происходит из истории всех событий зарядки/разрядки в отчете powercfg.

Другие вопросы по тегам