Где `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.