You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在C++程序中捕获Windows电源事件的替代机制咨询

捕获Windows电源切换事件的替代机制(除ETW外)

如果你要做C++程序捕获AC/DC切换事件,除了ETW,还有几种更接地气的Windows原生机制可以选:

1. WM_POWERBROADCAST消息(GUI程序首选)

这是窗口程序最常用的方式,不需要额外复杂配置。当系统电源状态变化时,Windows会给所有顶层窗口发送WM_POWERBROADCAST消息,其中wParam为PBT_APMPOWERSTATUSCHANGE时,就对应电源源切换(AC/DC互切)。

处理时可以调用GetSystemPowerStatus函数获取当前电源的具体状态,比如是否插电、电池剩余量等。代码示例:

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    switch (uMsg) {
        case WM_POWERBROADCAST:
            if (wParam == PBT_APMPOWERSTATUSCHANGE) {
                SYSTEM_POWER_STATUS powerStatus;
                if (GetSystemPowerStatus(&powerStatus)) {
                    if (powerStatus.ACLineStatus == AC_LINE_ON) {
                        // 切换到交流电,执行你的处理逻辑
                    } else {
                        // 切换到电池(直流电),执行你的处理逻辑
                    }
                }
            }
            return TRUE;
        // 其他消息处理逻辑...
    }
    return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

注意:这个方法必须依赖窗口和消息循环,纯控制台程序无法使用。

2. PowerSettingRegisterNotification(后台/无GUI程序)

如果你的程序是后台服务或无界面控制台程序,这个机制更合适——无需依赖窗口和消息循环。

你可以注册GUID_ACDC_POWER_SOURCE这个特定的电源设置事件,当AC/DC切换时,系统会直接调用你指定的回调函数。在回调里能获取事件触发的时间戳,以及当前电源状态。代码示例:

VOID CALLBACK PowerSettingCallback(
    PVOID Context,
    ULONG Type,
    PVOID Setting
) {
    if (Type == PBT_POWERSETTINGCHANGE) {
        PPOWERBROADCAST_SETTING pSetting = (PPOWERBROADCAST_SETTING)Setting;
        if (IsEqualGUID(pSetting->PowerSetting, GUID_ACDC_POWER_SOURCE)) {
            // 获取事件发生的本地时间
            SYSTEMTIME st;
            GetLocalTime(&st);
            // Data字段存储电源状态:0=电池,1=交流电
            DWORD powerSource = *(DWORD*)pSetting->Data;
            if (powerSource == 1) {
                // 切换到交流电的处理逻辑
            } else {
                // 切换到电池的处理逻辑
            }
        }
    }
}

// 注册通知(放在程序初始化阶段)
HANDLE hNotification = PowerSettingRegisterNotification(
    NULL,  // 无窗口时传NULL
    &GUID_ACDC_POWER_SOURCE,
    DEVICE_NOTIFY_CALLBACK,
    PowerSettingCallback,
    NULL,
    NULL
);

// 程序退出时记得注销通知
// PowerSettingUnregisterNotification(hNotification);

3. WMI(Windows管理规范)

如果你的程序需要获取更多深度电源相关信息(比如电池型号、供电设备详情),WMI是不错的选择。你可以订阅Win32_PowerManagementEvent类的事件,或者直接查询Win32_Battery、Win32_PowerSupply的状态变化。

在C++中实现WMI需要用到COM接口,步骤大致为:初始化COM环境、连接到WMI命名空间、创建事件查询语句(如SELECT * FROM Win32_PowerManagementEvent)、注册事件消费者。当电源切换时会收到事件通知,还能获取事件的时间戳属性。不过这个方法实现相对复杂,适合需要深度系统信息的场景。

各机制对比

机制适用场景优点缺点
WM_POWERBROADCASTGUI程序实现简单,无额外依赖必须依赖窗口和消息循环
PowerSettingRegisterNotification后台/无GUI程序轻量级,无窗口依赖,回调触发直接仅关注特定电源事件,信息维度有限
WMI需要深度系统电源信息的场景能获取丰富的系统电源相关数据实现复杂,需处理COM接口
ETW大规模事件追踪、日志记录性能高,适合批量事件分析配置和事件解析繁琐

内容的提问来源于stack exchange,提问作者Arun

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 02:56:14