28

I have created a small C# console app to move the pointer around the screen, in the hope that this would prevent the screen from sleeping / locking after a few minutes. Unfortunately the screen still goes to sleep after a few minutes.

Does anyone know if it's actually possible to write something in C# which will act like user input (either mouse or keyboard), and prevent the screen from sleeping / locking automatically?

Here is what I have, which I thought might do the trick:

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);
    }
}
John Smith
  • 7,243
  • 6
  • 49
  • 61
devklick
  • 2,000
  • 3
  • 30
  • 47
  • 1
    If you're actual goal is to prevent the screensaver running/monitor powering off, use the function that's designed for you to tell windows that - `SetThreadExecutionState`. More details [here](https://stackoverflow.com/questions/3665332/how-do-i-prevent-screen-savers-and-sleeps-during-my-program-execution) – Damien_The_Unbeliever Mar 01 '18 at 08:45
  • Annoyingly this has been asked before without answer and the OP doesn't have enough rep to be altruist and put a bounty on it https://stackoverflow.com/questions/38282770/stop-screensaver-programmatically – Jeremy Thompson Mar 01 '18 at 09:37

1 Answers1

46

You can make use of SetThreadExecutionState

Enables an application to inform the system that it is in use, thereby preventing the system from entering sleep or turning off the display while the application is running.

Remarks

Calling SetThreadExecutionState without ES_CONTINUOUS simply resets the idle timer; to keep the display or system in the working state, the thread must call SetThreadExecutionState periodically.

To run properly on a power-managed computer, applications such as fax servers, answering machines, backup agents, and network management applications must use both ES_SYSTEM_REQUIRED and ES_CONTINUOUS when they process events. Multimedia applications, such as video players and presentation applications, must use ES_DISPLAY_REQUIRED when they display video for long periods of time without user input. Applications such as word processors, spreadsheets, browsers, and games do not need to call SetThreadExecutionState.

DllImport

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

Enums

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

Usage

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

UPDATE 02/08/2021:

In case anyone is looking for a complete example, here is a project I found on github that has implemented this: https://github.com/pedrolcl/screensaver-disabler

Nicholas DiPiazza
  • 10,029
  • 11
  • 83
  • 152
TheGeneral
  • 79,002
  • 9
  • 103
  • 141
  • 9
    thanks for pointing this out. My question wasn't actually a true reflection of what I was after - I wanted to prevent the screen from locking as opposed to preventing the system from going to sleep. Any way, I achieved this with `SetThreadExecutionState(EXECUTION_STATE.ES_DISPLAY_REQUIRED | EXECUTION_STATE.ES_CONTINUOUS);` after you pointed out to use `SetThreadExecutionState`. Thanks! – devklick Apr 07 '18 at 18:04
  • 1
    Do we need to undo this change when the app closes ? Or are we supposed to call `PreventSleep()` at regular intervals ? – mrid Jun 18 '20 at 06:08
  • 2
    @mrid https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-setthreadexecutionstate, check out the flag comments – TheGeneral Jun 18 '20 at 06:11
  • 1
    @TheGeneral thanks. I went through that link. I'm making a monitoring software that would display a dashboard. So I should just use `ES_DISPLAY_REQUIRED` along with `ES_CONTINUOUS ` and call it periodically. Please correct me if I'm wrong – mrid Jun 18 '20 at 06:25
  • 2
    @mrid as far i know, it should be good until you set it otherwise, or someone else does. So in short, one call should do – TheGeneral Jun 18 '20 at 06:27
  • `SetThreadExecutionState(EXECUTION_STATE.ES_DISPLAY_REQUIRED | EXECUTION_STATE.ES_CONTINUOUS)` still does the trick for preventing the lock screen during RDP for Server 2016! – mdisibio Oct 30 '20 at 18:00
  • @TheGeneral Can this bypass windows domain policy for screen lock? – Ally Dec 02 '20 at 12:44
  • @Ally: yes it does – sɐunıɔןɐqɐp Jun 16 '21 at 08:41