.NET 阻止系统睡眠/息屏

本文介绍Windows系统设备下如何阻止系统睡眠/息屏,以及想看当前阻止睡眠/息屏的应用信息

powercfg /requests查看活动列表

在播放音乐时,我们会发现设置了系统电源管理-自动睡眠,计划不会生效,这个音频播放操作阻止了系统自动睡眠。但不会阻止息屏,所以Windows下一般屏幕关闭是不影响音频播放的

通过管理员CMD-powercfg /requests可以查看当前,应用程序和驱动程序电源请求相关列表:

这里看到是[DRIVER] Synaptics HD Audio,扬声器设备。

powercfg /requests详见 Powercfg 命令行选项 | Microsoft Learn,上面主要几个模式:

  • DIDPLAY 屏幕显示
  • SYSTEM 系统睡眠/休眠。
  • AWAYMODE 离开模式

阻止的可能有DRIVER、SERVICE,也可能是EXE。

比如服务使用阻止睡眠: [SERVICE] \Device\HarddiskVolume3\Program Files\Intel\Intel(R) Ready Mode Technology\IRMTService.exe,这是Intel提供的低功耗模式Intel® Ready Mode 技术 (Intel® RMT),基于这个状态可以在有需要时快速唤醒PC

基于上面几个模式,我们可以解析是哪些应用或者服务在活动、阻止睡眠/息屏。

.NET应用层阻止睡眠/息屏

上面这些阻止操作一般是系统应用实现的。我们开发的应用,也有阻止用户节能操作的场景

比如应用升级,我们想保障升级一次性完成,自动睡眠则会延长整个升级流程、造成不必要的风险。

复制代码
 1         [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
 2         private static extern EXECUTION_STATE SetThreadExecutionState(EXECUTION_STATE esFlags);
 3         /// <summary>
 4         /// 使应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入睡眠状态或关闭显示器。
 5         /// 通知应用之后的状态
 6         /// </summary>
 7         [FlagsAttribute]
 8         public enum EXECUTION_STATE : uint
 9         {
10             /// <summary>
11             /// 通知系统正在设置的状态应保持有效,直到使用 ES_CONTINUOUS 的下一次调用和清除其他状态标志之一。
12             /// </summary>
13             ES_CONTINUOUS = 0x80000000,
14             /// <summary>
15             /// 防止显示器关闭
16             /// </summary>
17             ES_DISPLAY_REQUIRED = 0x00000002,
18             /// <summary>
19             /// 防止系统进入睡眠
20             /// </summary>
21             ES_SYSTEM_REQUIRED = 0x00000001
22         }

SetThreadExecutionState是WIN32 Winbase下的一个系统函数,给应用程序提供接口:通知系统它正在使用中,从而防止系统在应用程序运行时进入睡眠状态或关闭显示器。详见SetThreadExecutionState 函数 (winbase.h) - Win32 apps | Microsoft Learn

上面还有一个ES_AWAYMODE_REQUIRED未列出来,使用并不多,只能由多媒体应用使用,用于睡眠时执行关键后台处理。

另外,函数执行有返回状态值。如果函数成功,则返回值为上一个线程执行状态。
调用此函数,实现阻止系统睡眠的操作:

复制代码
 1     /// <summary>
 2     /// 阻止系统睡眠/息屏
 3     /// </summary>
 4     public static EXECUTION_STATE PreventSleep()
 5     {
 6         return SetThreadExecutionState(EXECUTION_STATE.ES_CONTINUOUS | EXECUTION_STATE.ES_SYSTEM_REQUIRED | EXECUTION_STATE.ES_DISPLAY_REQUIRED);
 7     }
 8 
 9     /// <summary>
10     /// 允许系统睡眠
11     /// </summary>
12     public static EXECUTION_STATE AllowSleep()
13     {
14         return SetThreadExecutionState(EXECUTION_STATE.ES_CONTINUOUS);
15     }

这里阻止了睡眠以及息屏的操作

.NET快速查询活动状态

上面是使用.NET在应用中阻止系统进行睡眠以及息屏。.NET还可以通过WIN32直接查询这些阻止请求的总状态,是否可执行睡眠、是否可执行息屏?

CallNtPowerInformation 函数能即时的获取当前系统电源策略状态值,详见 CallNtPowerInformation 函数 (powerbase.h) - Win32 apps | Microsoft Learn

复制代码
1         [DllImport("Powrprof.dll", CharSet = CharSet.Auto, SetLastError = true)]
2         private static extern uint CallNtPowerInformation(
3             SystemInformationClass information,
4             IntPtr inputBuffer,
5             uint inputBufferLength,
6             IntPtr outputBuffer,
7             uint outputBufferLength
8         );

封装一下,获取系统执行状态:

复制代码
 1     /// <summary>
 2     /// 获取系统执行状态
 3     /// 0表示无,可正常睡眠、息屏
 4     /// 1表示阻止睡眠中,系统无法睡眠
 5     /// 2表示阻止息屏中,系统无法息屏
 6     /// 3表示阻止睡眠以及息屏中,系统无法睡眠、息屏
 7     /// </summary>
 8     /// <returns>返回系统执行状态,如果查询失败,返回<see cref="EXECUTION_STATE.ES_CONTINUOUS"/></returns>
 9     public static EXECUTION_STATE GetSystemExecutionState()
10     {
11         IntPtr ptr = Marshal.AllocHGlobal(sizeof(uint));
12         if (CallNtPowerInformation(SystemInformationClass.SystemExecutionState,
13                 IntPtr.Zero, 0, ptr, sizeof(uint)) == 0)
14         {
15             var objectState = Marshal.PtrToStructure(ptr, typeof(uint));
16             var stringState = objectState?.ToString();
17             if (stringState != "0" && Enum.TryParse(stringState, out EXECUTION_STATE state))
18             {
19                 return state;
20             }
21         }
22         return EXECUTION_STATE.ES_CONTINUOUS;
23     }

所以获取这个状态,可用于那些即将执行睡眠/息屏的功能,在执行前可确认此操作能否正常执行,提升用户操作的准确性。

相关推荐
流星白龙4 小时前
【Linux】35.封装 UdpSocket(2)
linux·运维·windows
waicsdn_haha5 小时前
Visual Studio Code 2025 安装与高效配置教程
c语言·ide·windows·vscode·微软·编辑器·win7
ChoSeitaku6 小时前
12.重复内容去重|添加日志|部署服务到Linux上(C++)
linux·c++·windows
Major_xx7 小时前
装win10系统提示“windows无法安装到这个磁盘,选中的磁盘采用GPT分区形式”解决方法
windows·gpt
CoderIsArt7 小时前
Windows图形开发库Kernel32,OpenGL32,Glu32,Gdi32与User32
windows
伪装成塔的小兵7 小时前
Windows使用docker部署fastgpt出现的一些问题
windows·docker·容器·oneapi·fastgpt
开开心心就好8 小时前
娱乐使用,可以生成转账、图片、聊天等对话内容
windows·python·智能手机·软件工程·娱乐·软件需求
~kiss~10 小时前
python的thrift2pyi学习
windows·python·学习
爱学习的大牛12311 小时前
ZLMediaKit Windows 编译指南
windows
rkmhr_sef21 小时前
Redis 下载与安装 教程 windows版
数据库·windows·redis