以编程方式阻止 Windows 屏幕保护程序启动
是否有推荐的方法来阻止 Windows 屏幕保护程序启动? 我发现的最接近的是这篇文章,但我真正喜欢的是要做的只是告诉 Windows 计算机没有空闲,而不是愚弄当前设置的屏幕保护程序值。
Is there a recommended way to prevent the Windows screensaver from starting? The closest thing I've found is this article, but what I would really like to do is just tell Windows that the computer isn't idle rather than fooling with the currently set screensaver values.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(14)
为了进行测试,我将屏幕保护程序设置为 1 分钟并需要密码。
我尝试捕获 SC_SCREENSAVE 并在 VB .Net 中返回 -1。 正如所评论的,它在没有屏幕保护程序密码时有效,但如果屏幕保护程序密码处于活动状态,则失败。 (我在Windows XP 中尝试过)。 我还将其放入计时器的滴答事件中,每 1000 毫秒一次:
它不起作用。 光标来回晃动,1 分钟后屏幕保护程序会短暂闪烁,然后关闭。 屏幕保护程序只打开一会儿,不足以要求输入密码。 但闪光灯还是很难看。
然后我尝试使用user32.dll的SetCursorPos和GetCursorPos。 您可以在 pinvoke 上查找它们。 与上面的结果相同。
然后我查看了这个问题其他地方提到的“JiggleMouse”的代码。 JiggleMouse 使用 SendInput。 SendInput 有效! 屏幕保护程序不闪烁。 我在计时器内调用了 SendInput,每 50 秒触发一次(略小于屏幕保护程序的最小超时时间 60 秒)。 将鼠标移动 0,0 增量就足够了,没有真正的移动。 这确实有效。 放入 Tick 事件的代码:
来自 pinvoke.com:
For testing, I set the screensaver to 1 minute and required a password.
I tried capturing SC_SCREENSAVE and returning -1 in VB .Net. As commented, it works when there is no screensaver password but fails if the screensaver password is active. (I tried it in Windows XP). I also put this into a Timer's tick event, every 1000 milliseconds:
It doesn't work. The cursor jiggles back and forth and after 1 minute the screensaver flashes on for a short instance and then turns off. The screensaver turns on for only a moment, not long enough to require a password. But still, the flash is ugly.
Then I tried using user32.dll's SetCursorPos and GetCursorPos. You can look them up at pinvoke. Same result as above.
Then I peeked at the code of "JiggleMouse" mentioned elsewhere in this question. JiggleMouse uses SendInput. SendInput works! No flash of the screensaver. I put a call to SendInput inside of a Timer that triggers every 50 seconds (just less than the minimum screensaver timeout of 60 seconds). It's sufficient to move the mouse by a delta of 0,0, no real movement. That does work. The code to put in the Tick event:
This comes from pinvoke.com:
在 Windows 7+ 中,将电源管理 API 的
PowerSetRequest()
与PowerRequestDisplayRequired
结合使用https://msdn.microsoft.com/en-us/library/windows/desktop/dd405534(v=vs.85)。 aspx
在以前版本的 Windows 中,拦截 WM_SYSCOMMAND - SC_SCREENSAVE 消息,如 Eddie Parker 的回答中所述。
In Windows 7+, use the Power Management API's
PowerSetRequest()
withPowerRequestDisplayRequired
https://msdn.microsoft.com/en-us/library/windows/desktop/dd405534(v=vs.85).aspx
In previous versions of windows, intercept the WM_SYSCOMMAND - SC_SCREENSAVE message as detailed in Eddie Parker's answer.
微妙的。 告诉Windows系统不空闲的官方方法是SetThreadExecutionState。 这会重置空闲计时器(或者如果您传递 ES_CONTINUOUS 则将其关闭)。 但是,即使 SetThreadExecutionState 重置空闲计时器,它也不会停止屏幕保护程序!
Subtle. The official way to tell Windows that the system is not idle is SetThreadExecutionState. This resets the idle timer, (or turns it off, if you pass
ES_CONTINUOUS
). However, even though SetThreadExecutionState resets the idle timer, it does not stop the screensaver!我使用 Mouse Jiggler 重置空闲状态。 这绕过了一个组策略,该策略往往会在不合时宜的时间启动我的屏幕保护程序(并锁定机器):当我正在阅读长文档、研究复杂的代码块或在谈话期间说/听/不经常打字时会议。
由于让鼠标每秒对角跳 1px 可能有点烦人,我打算使用 AutoHotKey 编写一个脚本执行基本相同的操作,但仅在配置的键盘/鼠标空闲超时之后,并且可能使用 Shift 键(或 Scroll Lock)而不是鼠标移动。
I use Mouse Jiggler to reset the idle state. This gets around a Group Policy that tends to start my screensaver (and lock the machine) at inopportune times: when I'm reading a long document, studying a complex chunk of code, or talking/listening/not-constantly-typing during a meeting.
As it can be slightly annoying to have the mouse jump 1px diagonally every second, I intend to use AutoHotKey to write a script that does basically the same thing, but only after a configured keyboard/mouse idle timeout, and maybe use the Shift key (or Scroll Lock) instead of a mouse move.
来自 MSDN:
但有一个警告:
即使您将 SetThreadExecutionState 与 ES_CONTINUOUS 一起使用,这似乎也适用。
因此,如果没有警告,您的选择将是:
最后一个选项很好,因为它甚至可以使用密码保护策略。
From MSDN:
There's a caveat though:
That seems to apply even if you use the SetThreadExecutionState with ES_CONTINUOUS.
So, if it weren't for the caveat, your choices would be:
The last option is nice in that it works even with the password protection policy.
SystemParametersInfo
具体来说,
SPI_SETSCREENSAVEACTIVE< /代码> 参数。
这不行吗? 我很惊讶我在这里没有看到它。 请注意,SetThreadExecutionState 根本不会影响屏幕保护程序,只会影响显示器的休眠。
SystemParametersInfo
Specifically, the
SPI_SETSCREENSAVEACTIVE
parameter.Does this not work? I was surprised that I did not see it here. Note that SetThreadExecutionState will not affect the screen saver at all, just the sleeping of the display.
这篇博文详细介绍了您需要在 C++ 中做什么。
来自网站的实际代码片段:
}
This blog post details what you need to do in C++.
The actual code snippet from the website:
}
正如 Adrian McCarthy 在 MSDN 表示:
因此,使用 UINT SC_SCREENSAVE 从 WM_SYSCOMMAND 捕获事件,并通过返回 0 或创建假鼠标移动(“mouse_event(MOUSEEVENTF_MOVE, 0, 1, 0, 0)”)来丢弃它,如果用户启用了受密码保护的屏幕保护程序选项。
使用 SetThreadExecutionState winAPI 告诉即使用户没有与计算机交互,操作系统也会识别该线程正在使用中。 这些将防止出现屏幕保护程序并阻止机器自动暂停。
有一系列标志用于指定当前线程的新状态:
重置显示器空闲计时器。
通过重置系统空闲计时器进入工作状态。
设置应保持有效,直到下一次调用使用
ES_CONTINUOUS 和其他状态标志之一被清除。
如果有人想在 C# 中使用它,必须PInvoke:
用户定义类型:
这里下面是调用过程:
根据MSDN 此 API 使用起来也很安全。
如果应用程序在重置标志之前崩溃,系统将进行调整并自动重置。
As Adrian McCarthy mentioned from MSDN that :
So catch the event from WM_SYSCOMMAND using UINT SC_SCREENSAVE and discarded it by returning 0 or by creating a fake mouse move ("mouse_event(MOUSEEVENTF_MOVE, 0, 1, 0, 0)") will not work properly if the user enabled password-protected screen saver option.
Use SetThreadExecutionState winAPI to tell the operating system that the thread is in use, even if the user is not interacting with the computer. These will prevent to appear screen saver and stop the machine from being suspended automatically.
There are series of flags to specify a new state for the current thread:
resetting the display idle timer.
working state by resetting the system idle timer.
set should remain in effect until the next call that uses
ES_CONTINUOUS and one of the other state flags are cleared.
If someone wants to use this in C#, must have to PInvoke this :
User-Defined Types:
Here below is the calling procedure:
According to MSDN this API is safe also to use.
If the Application crashed before resetting flag, the System will adjust and will reset automatically.
不敢相信没有人指出简单而明显的解决方案:
Can't believe no one has pointed out the easy and obvious solution:
您可以使用 SystemParametersInfo
获取
SCREENSAVETIMEOUT
,然后立即将超时设置回相同的值。 只要您想阻止屏幕保护程序继续运行,就定期在计时器上执行此操作。这具有重置当前倒计时器的效果,而无需实际更改系统设置。
您可能还想调用
SetThreadExecutionState
来影响其他答案提到的电源。You can use SystemParametersInfo
to get the
SCREENSAVETIMEOUT
and then immediately set the timeout back to the same value. Do this periodically on a timer for as long as you want to prevent the screensaver from going on.This has the effect of resetting the current countdown timer without actually changing the system setting.
You probably also want to call
SetThreadExecutionState
to affect the power as other answers mention.重置超时计数器即可
只需使用SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, 1, nil, SPIF_SENDWININICHANGE);
Just reset the timeout counter with
SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, 1, nil, SPIF_SENDWININICHANGE);
来自 JD 设计免费软件 - Flipss.exe(下载 12kb) 是一个命令行实用程序,将为您设置 SPI_SETSCREENSAVEACTIVE。
From JD Design Freeware - Flipss.exe (download 12kb) is a command line utility that will set SPI_SETSCREENSAVEACTIVE for you.
我意识到这是一个旧线程,但我第一次面临这个问题(工作机器完全锁定,就更改超短睡眠时间、屏幕保护程序等而言)-我什至无法更改我的桌面背景)。 我环顾四周的解决方案,有些看起来过于复杂,有些......不是那么复杂。
我的一些同事正在使用咖啡因。 但这肯定是某种间谍软件等,因为如果没有开放的互联网连接,它就拒绝运行。
所以我发现了这个(并稍微修改了它),这正是 Caffeine 所做的(除了 Caffeine 每 59 秒执行一次),而没有所有......充其量是膨胀软件。
在 PowerShell 中,执行以下 2 行命令行:
或者,如果您愿意,也可以将其设为单行:(
后者似乎会泄漏内存,但似乎根本不会泄漏)
一旦运行其中任何一个,你的屏幕不会锁定,直到你执行 ctrl-c 或关闭 Powershell 窗口(仅在后一个版本中,似乎 ctrl-c 可能不会发生,直到睡眠间隔过去)。
请注意,至少在我见过的任何键盘上都没有 F15 键(但它是合法的 Windows 按键),因此没有副作用。 现在,如果您的 IT 部门。 异常偏执,他们可能会标记 F15 按键(我的就是超级偏执,但他们几个月来都没有注意到任何事情)。 如果是这样,请改用滚动锁定之类的东西。
这两个在我的win10机器上100%工作。 简单就好!
I realize this is an old thread, but I'm faced with this issue for the first time (work machine is totally locked down, as far as changing super short sleep time, screensaver, etc. - I can't even change my desktop background). I've looked around at solutions, some seemingly way overcomplicated and some...not so much.
Some of my colleagues are using Caffeine. But that is surely some kind of spyware, etc., as it refuses to run if there is not an open internet connection.
So I found this (and modified it slightly), which is exactly what Caffeine does (except Caffeine does it every 59 seconds), without all the...at best, bloatware.
In PowerShell, execute the following 2 command lines:
Or you can make it a one-liner if you like:
(the latter of which seems like it would leak memory, but it does not seem to at all)
Once you run either of those, your screen will NOT lock, until you do ctrl-c, or close the Powershell window (in the latter version only, it seems, the ctrl-c may not happen until the sleep interval elapses).
Note that there is no F15 key, at least on any keyboard I've ever seen (but it's a legit windows keystroke), so there are no side effects. Now, if you your IT dept. is exceptionally paranoid, they may flag an F15 keystroke (mine is super paranoid, but they haven't noticed anything for months). If so, use something like scroll-lock instead.
Both of these 100% work on my win10 machine. Simple is good!
AutoHotkey 可以使用脚本中的 1 行 DllCall 设置 SystemParametersInfo(SPI_SETSCREENSAVEACTIVE),以便使用 .ahk 脚本轻松完成此操作。
用于禁用屏幕保护程序的 AutoHotkey 代码:
用于启用屏幕保护程序的 AutoHotkey 代码:
参考论坛主题:
F13Key - 使用 SystemParametersInfo 切换屏幕保护程序
SKAN - 如何暂时禁用屏幕保护程序
AutoHotkey can set SystemParametersInfo(SPI_SETSCREENSAVEACTIVE) with a 1-liner DllCall in script to easily accomplish this with a .ahk script.
AutoHotkey code to disable Screensaver:
AutoHotkey code to enable screensaver:
Reference Forum Threads:
F13Key - Toggling Screen Saver with SystemParametersInfo
SKAN - How to Disable Screen Saver Temporarily