Win10下ctypes调用SetThreadExecutionState后无法恢复屏保问题
Win10 屏保被SetThreadExecutionState永久阻止的排查与修复
核心踩坑点说明
SetThreadExecutionState的生效范围是调用该API的线程所属进程,不是全局系统配置。只要有进程调用时传了0x80000002(即ES_CONTINUOUS | ES_DISPLAY_REQUIRED)且没有正常退出重置状态,哪怕你在其他新进程里反复传0x80000000,也清不掉这个进程持有的显示常亮锁,系统会一直判定有应用需要保持屏幕点亮,自然不会触发屏保。
分步排查修复流程
- 第一步:清理所有残留相关进程
打开任务管理器的「详细信息」选项卡,把所有python.exe、pythonw.exe、以及你打包生成的屏保控制程序进程全部结束。注意很多人会把这类脚本设为无窗口后台运行,出问题时很容易漏掉后台挂着的pythonw.exe进程。清完之后等够你设置的屏保等待时长,验证是否能正常触发。 - 第二步:手动重置系统执行状态
以管理员权限打开PowerShell,逐行执行以下代码,执行完不要立刻关窗口,等10秒再关闭:import ctypes # 清空所有显示、睡眠阻止标志 ctypes.windll.kernel32.SetThreadExecutionState(0x80000000) # 传0彻底重置当前线程的执行状态配置 ctypes.windll.kernel32.SetThreadExecutionState(0x0) - 第三步:排查其他持有显示锁的应用
如果前两步操作完屏保还是不触发,说明不是你写的脚本残留,用系统自带工具查所有持有显示锁的进程:
管理员权限下执行命令:powercfg /requests
查看返回结果中[DISPLAY]分类下列出的进程,除系统自带的资源管理器外,视频播放器、浏览器(正在播放网页视频/直播时会持锁)、会议软件、远程桌面类程序全部手动退出,这类程序同样会调用相同API阻止屏保启动。 - 第四步:重置电源计划到默认
极少数情况是异常API调用打乱了电源计划配置,直接执行命令powercfg -restoredefaultschemes重置所有电源计划为系统默认,执行完重启电脑,重新设置屏保等待时长即可。
原有控制脚本的修正方案
你之前写的脚本缺少退出兜底逻辑,一旦程序崩溃、被任务管理器强杀,根本走不到重置状态的逻辑,就会出现这次的残留锁问题。修正后的基础逻辑参考:
import ctypes import atexit # 常量定义 ES_CONTINUOUS = 0x80000000 ES_DISPLAY_REQUIRED = 0x00000002 def _reset_state(): # 退出时强制重置为允许屏保状态 ctypes.windll.kernel32.SetThreadExecutionState(ES_CONTINUOUS) # 注册退出钩子,程序正常退出、抛异常退出时都会自动执行重置 atexit.register(_reset_state) def block_screensaver(): # 阻止屏保、熄屏 ctypes.windll.kernel32.SetThreadExecutionState(ES_CONTINUOUS | ES_DISPLAY_REQUIRED) def allow_screensaver(): # 恢复允许屏保 ctypes.windll.kernel32.SetThreadExecutionState(ES_CONTINUOUS) # 程序启动时先主动重置一次,清掉上次运行可能残留的锁 allow_screensaver()
注意:即便是加了退出钩子,如果是直接拔电源、任务管理器强制结束进程树这类极端操作,还是可能出现状态残留,启动时主动重置的逻辑不能省。
内容的提问来源于stack exchange,提问作者Alex B
相关产品推荐
相关产品推荐

