.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     }

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

相关推荐
cpsvps_net7 小时前
美国服务器环境下Windows容器工作负载智能弹性伸缩
windows
甄超锋8 小时前
Java ArrayList的介绍及用法
java·windows·spring boot·python·spring·spring cloud·tomcat
cpsvps10 小时前
美国服务器环境下Windows容器工作负载基于指标的自动扩缩
windows
网硕互联的小客服13 小时前
Apache 如何支持SHTML(SSI)的配置方法
运维·服务器·网络·windows·php
etcix13 小时前
implement copy file content to clipboard on Windows
windows·stm32·单片机
许泽宇的技术分享13 小时前
Windows MCP.Net:基于.NET的Windows桌面自动化MCP服务器深度解析
windows·自动化·.net
非凡ghost14 小时前
AMS PhotoMaster:全方位提升你的照片编辑体验
windows·学习·信息可视化·软件需求
mortimer16 小时前
一次与“顽固”外部程序的艰难交锋:subprocess 调用exe踩坑实录
windows·python·ai编程
gameatp18 小时前
从 Windows 到 Linux 服务器的全自动部署教程(免密登录 + 压缩 + 上传 + 启动)
linux·服务器·windows
穷人小水滴18 小时前
在 windows 运行 flatpak 应用 (WSL)
linux·windows·ubuntu