使用C#防止屏幕睡眠

29

我创建了一个小的C#控制台应用程序来移动屏幕上的指针,希望这样可以防止屏幕在几分钟后进入睡眠/锁定状态。不幸的是,屏幕仍然会在几分钟后进入睡眠状态。

有人知道是否实际上可以编写一些C#代码来模拟用户输入(鼠标或键盘),并防止屏幕自动进入睡眠/锁定状态吗?

这是我所拥有的,我认为它可能会奏效:

class Program
{
    [DllImport("user32.dll")]
    static extern bool SetCursorPos(int X, int Y);

    static Random rnd = new Random();

    static void Main(string[] args)
    {

        Rectangle screenRes = Screen.PrimaryScreen.Bounds;
        int widtMax = screenRes.Width;
        int heighMax = screenRes.Height;

        int w;
        int h;

        do
        {
            while (!Console.KeyAvailable)
            {
                w = rnd.Next(1, widtMax);
                h = rnd.Next(1, heighMax);

                SetCursorPos(w, h);
                System.Threading.Thread.Sleep(1000);
            }
        } while (Console.ReadKey(true).Key != ConsoleKey.Escape);
    }
}

2
如果你的实际目标是防止屏幕保护程序运行/监视器关闭,请使用专为此设计的函数告诉Windows - SetThreadExecutionState。更多细节请参见这里 - Damien_The_Unbeliever
令人烦恼的是,此前已经有人提出了同样的问题,但没有得到答案,而且该帖子的发帖者没有足够的声望来慷慨解囊并设置赏金。https://stackoverflow.com/questions/38282770/stop-screensaver-programmatically - Jeremy Thompson
1个回答

49

您可以利用SetThreadExecutionState方法。

启用应用程序通知系统正在使用,从而防止系统在应用程序运行时进入睡眠状态或关闭显示器。

备注

仅使用ES_CONTINUOUS调用SetThreadExecutionState会重置空闲计时器;为了保持显示器或系统处于工作状态,线程必须定期调用SetThreadExecutionState

为了正常在受电源管理的计算机上运行,应用程序(例如传真服务器、答录机、备份代理和网络管理应用程序)在处理事件时必须同时使用ES_SYSTEM_REQUIREDES_CONTINUOUS。多媒体应用程序(例如视频播放器和演示文稿应用程序)在长时间显示视频且没有用户输入时必须使用ES_DISPLAY_REQUIRED。文字处理器、电子表格、浏览器和游戏不需要调用SetThreadExecutionState

DllImport

[DllImport("kernel32.dll", CharSet = CharSet.Auto,SetLastError = true)]
static extern EXECUTION_STATE SetThreadExecutionState(EXECUTION_STATE esFlags);

枚举类型

[FlagsAttribute]
public enum EXECUTION_STATE :uint
{
     ES_AWAYMODE_REQUIRED = 0x00000040,
     ES_CONTINUOUS = 0x80000000,
     ES_DISPLAY_REQUIRED = 0x00000002,
     ES_SYSTEM_REQUIRED = 0x00000001
     // Legacy flag, should not be used.
     // ES_USER_PRESENT = 0x00000004
}

用法

void PreventSleep ()
{
    // Prevent Idle-to-Sleep (monitor not affected) (see note above)
    SetThreadExecutionState(EXECUTION_STATE.ES_CONTINUOUS | EXECUTION_STATE.ES_AWAYMODE_REQUIRED);
}

更新于2021年2月8日:

如果有人正在寻找一个完整的示例,这里是我在Github上发现的一个项目,它已经实现了这个功能:https://github.com/pedrolcl/screensaver-disabler


9
谢谢指出这一点。我的问题实际上并没有真正反映我想要的 - 我想防止屏幕锁定,而不是防止系统进入睡眠状态。无论如何,在你指出使用SetThreadExecutionState后,我用SetThreadExecutionState(EXECUTION_STATE.ES_DISPLAY_REQUIRED | EXECUTION_STATE.ES_CONTINUOUS); 实现了这个目标。谢谢! - devklick
1
当应用程序关闭时,我们需要撤销这个更改吗?还是我们应该定期调用“PreventSleep()”? - mrid
2
请查看@mrid https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-setthreadexecutionstate,了解标志注释。 - TheGeneral
1
@TheGeneral 谢谢。我看了那个链接。我正在制作一个监控软件,它将显示一个仪表板。所以我应该只使用 ES_DISPLAY_REQUIREDES_CONTINUOUS 并定期调用它。如果我错了,请纠正我。 - mrid
2
据我所知,除非您另行设置或其他人这样做,否则它应该是良好的。因此,简而言之,一个调用应该就可以了。 - TheGeneral
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接