Windows 用 GetSystemPowerStatus 获取电池状态,需检查返回值及 BatteryLifePercent 是否为255;温度无原生API,WMI常失效,推荐OpenHardwareMonitor;Linux通过/sys/class/power_supply/和/sys/class/hwmon/读取。

Windows 上用 GetSystemPowerStatus 获取电池电量和充电状态
Windows 提供了稳定、无需额外权限的 API 来读取电池信息,GetSystemPowerStatus 是最直接的选择。它返回一个 SYSTEM_POWER_STATUS 结构体,包含 ACLineStatus(市电连接状态)、BatteryFlag(电池健康/状态标记)、BatteryLifePercent(剩余电量百分比)等字段。
常见错误是忽略返回值检查或未处理无电池设备(如台式机):调用后必须检查函数返回值是否为 TRUE,否则结构体内容不可信;若 ACLineStatus == 255(AC_LINE_UNKNOWN)且 BatteryFlag == 255(BATTERY_FLAG_UNKNOWN),基本可判定设备无电池或驱动未上报。
- 需包含头文件:
#include <windows.h></windows.h>和#include <powrprof.h></powrprof.h>(后者声明该函数) - 链接时加
powrprof.lib,否则链接失败报LNK2019: unresolved external symbol __imp__GetSystemPowerStatus@4 -
BatteryLifePercent在电池耗尽或未校准状态下可能为 255(BATTERY_PERCENT_UNKNOWN),应过滤该值
// 示例片段
SYSTEM_POWER_STATUS sps = {};
if (GetSystemPowerStatus(&sps)) {
if (sps.BatteryLifePercent != 255) {
printf("Battery: %d%%
", sps.BatteryLifePercent);
printf("AC connected: %s
", sps.ACLineStatus == 1 ? "yes" : "no");
}
}
Windows 下读取硬件温度需绕过 WMI 或使用 OpenHardwareMonitor 等开源库
Windows 内核不暴露标准化的「CPU 温度」API。官方途径只有 WMI 的 MSAcpi_ThermalZoneTemperature 类,但它在多数 OEM 设备上被禁用或返回无效值(如恒定 2732 或 0),且需要启用 WMI 服务、管理员权限,并受 UEFI/ACPI 实现质量严重制约。
更实际的做法是复用成熟开源项目的数据采集逻辑。例如 OpenHardwareMonitor(C#)提供完整驱动级传感器访问,其 C++ 封装版 LibreHardwareMonitor 可通过 DLL 导出函数调用;或者直接解析 Intel RAPL 接口(仅限部分 Intel CPU)获取封装温度估算值。
立即学习“C++免费学习笔记(深入)”;
- WMI 查询示例命令:
wmic /namespace:\root\wmi PATH MSAcpi_ThermalZoneTemperature get CurrentTemperature—— 返回值需除以 10 得摄氏度,但多数笔记本返回0或2732(即 0℃,明显错误) - 使用
LibreHardwareMonitor需加载其LHM.dll,调用Initialize()后遍历Computer.CPU[0].Sensors查找Temperature类型传感器 - 纯原生方案几乎不可行:没有管理员权限无法访问 MSR 寄存器;不同芯片组(Intel/AMD)寄存器地址与解码方式完全不同;BIOS 可能屏蔽相关 ACPI 表
Linux 下用 /sys/class/power_supply/ 和 /sys/class/hwmon/ 文件系统获取数据
Linux 不依赖 API 调用,而是通过标准 sysfs 接口暴露电池与温度信息,稳定且无需 root(读取权限通常开放)。路径固定、格式简单,适合 shell 脚本或 C++ 中用 fopen + fgets 解析。
关键路径:
- 电池状态:
/sys/class/power_supply/BAT0/status(Charging/Discharging)、/sys/class/power_supply/BAT0/capacity(整数百分比) - 温度传感器:
/sys/class/hwmon/hwmon*/temp*_input,值为毫摄氏度(如52345→ 52.345℃),需遍历所有 hwmon 目录并匹配name文件确认来源(如coretemp、k10temp) - 注意:
BAT0可能是BAT1或axp288_fuel_gauge(ARM 平板),应先读/sys/class/power_supply/下所有子目录名再筛选含energy或charge字段的目录
// 示例:读取电量(C++ 片段)
std::ifstream f("/sys/class/power_supply/BAT0/capacity");
int cap;
if (f >> cap) std::cout << "Battery: " << cap << "%
";
跨平台方案本质是「分发+适配」,不是统一 API
不存在一套 C++ 代码在 Windows/Linux/macOS 上都用同一个系统调用拿到温度。macOS 需用 IOKit(IOServiceGetMatchingServices + AppleSMC 键值),且仅支持部分机型;而 Linux 的 hwmon 命名规则和 Windows 的 WMI 完全无关。
真正可行的工程做法是:编译期条件编译(#ifdef _WIN32 / #ifdef __linux__),对每种平台单独实现最小可行采集逻辑,并预留 fallback(如温度缺失时返回 -1 或跳过该指标)。别试图抽象出 getBatteryPercent() 这样的通用接口——底层差异太大,强行统一只会让错误更隐蔽。
最容易被忽略的是权限与稳定性边界:Windows 上普通用户可读电池,但温度几乎总要管理员;Linux 上某些 hwmon 节点权限为 600,普通用户读不到;所有平台都存在传感器未就绪(刚开机)、驱动未加载、虚拟机无对应设备等情况。采集前必须做存在性检查和容错解析,而不是假设路径一定存在、文件一定可读、数值一定合法。


















