Prevent windows from going into sleep when my program is running?
Asked Answered
A

8

43

I have to stop windows from going into sleep when my program is running.

And I don't only want to prevent the sleep-timer, I also want to cancel the sleep-event if I press the sleep-button or in any other way actively tell the computer to sleep. Therefore SetThreadExecutionState is not enough.

Or...I don't actually have to prevent the sleep completely, only delay it 5-10sec to allow my program to finish a task.

(I know that this is bad program behavior but it's only for personal use.)

Amphibiotic answered 10/3, 2009 at 7:41 Comment(0)
M
23

I had a problem like this with a hardware device connected via usb. XP /Vista would sleep/hibernate right in the middle of ... Great you say, when it resumes it can just continue. If the hardware is still connected!!! Users have the habit of pulling cables out whenever they feel like it.

You need to handle XP and Vista

Under XP trap the WM_POWERBROADCAST and look for the PBT_APMQUERYSUSPEND wparam.

   // See if bit 1 is set, this means that you can send a deny while we are busy
   if (message.LParam & 0x1)
   {
      // send the deny message
      return BROADCAST_QUERY_DENY;
   } // if
   else
   {
      return TRUE;
   } // else

Under Vista use SetThreadExecutionState like this

// try this for vista, it will fail on XP
if (SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED | ES_AWAYMODE_REQUIRED) == NULL)
{
   // try XP variant as well just to make sure 
   SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED);
}  // if 

and when you app has finished set it back to normal

// set state back to normal
SetThreadExecutionState(ES_CONTINUOUS);
Midst answered 10/3, 2009 at 8:6 Comment(7)
Hmm, i was wrong, SetThreadExecutionState actually did work, just had to set the ES_AWAYMODE_REQUIRED also. The strange thing is that my monitor goes black but the system never fully goes to sleep.Amphibiotic
That's what away mode is all about. The idea is that the computer would normally be sleeping, so it's made to look like it's sleeping. Then when the background task is done (e.g. recording a TV show), the app turns off the system required and away mode bits and the computer actually does go to sleep.Cartridge
>The strange thing is that my monitor goes black but the system never fully goes to sleep --- maybe that's just the default empty screen saver?Provincial
Here's a link to the Window Message to save anyone the google: msdn.microsoft.com/en-us/library/windows/desktop/…Sightseeing
Will SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED); work for WinXP?Anguiano
I'm still unclear on how ES_AWAYMODE_REQUIRED differs from ES_SYSTEM_REQUIRED.Dukedom
@AlexBudovski AFAIU ES_AWAYMODE_REQUIRED changes sleep mode to keep the CPU/system actually running, even when the user closes a laptop for instance. ES_SYSTEM_REQUIRED tells the system to stay awake without any user input.Wilmerwilmette
G
27

After considering vim's answer

"Using PowerCreateRequest, PowerSetRequest, and PowerClearRequest functions is the preferred method."

with the linked AvailabilityRequests.docx on msdn which is exhausting to get into it (too much to read), I have searched the web for a concrete example in that is based on the PowerCreateRequest and found http://go4answers.webhost4life.com/Example/problem-monitor-wakeup-service-windows7-12092.aspx [EDIT 2016 - isn't available anymore]

Copied and adapted it to my needs (PInvoke of CloseHandle copied from msdn):

using System.Runtime.InteropServices;

    #region prevent screensaver, display dimming and automatically sleeping
    POWER_REQUEST_CONTEXT _PowerRequestContext;
    IntPtr _PowerRequest; //HANDLE

    // Availability Request Functions
    [DllImport("kernel32.dll")]
    static extern IntPtr PowerCreateRequest(ref POWER_REQUEST_CONTEXT Context);

    [DllImport("kernel32.dll")]
    static extern bool PowerSetRequest(IntPtr PowerRequestHandle, PowerRequestType RequestType);

    [DllImport("kernel32.dll")]
    static extern bool PowerClearRequest(IntPtr PowerRequestHandle, PowerRequestType RequestType);

    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
    internal static extern int CloseHandle(IntPtr hObject);

    // Availablity Request Enumerations and Constants
    enum PowerRequestType
    {
        PowerRequestDisplayRequired = 0,
        PowerRequestSystemRequired,
        PowerRequestAwayModeRequired,
        PowerRequestMaximum
    }

    const int POWER_REQUEST_CONTEXT_VERSION = 0;
    const int POWER_REQUEST_CONTEXT_SIMPLE_STRING = 0x1;
    const int POWER_REQUEST_CONTEXT_DETAILED_STRING = 0x2;

    // Availablity Request Structures
    // Note:  Windows defines the POWER_REQUEST_CONTEXT structure with an
    // internal union of SimpleReasonString and Detailed information.
    // To avoid runtime interop issues, this version of 
    // POWER_REQUEST_CONTEXT only supports SimpleReasonString.  
    // To use the detailed information,
    // define the PowerCreateRequest function with the first 
    // parameter of type POWER_REQUEST_CONTEXT_DETAILED.
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    public struct POWER_REQUEST_CONTEXT
    {
        public UInt32 Version;
        public UInt32 Flags;
        [MarshalAs(UnmanagedType.LPWStr)]
        public string
            SimpleReasonString;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct PowerRequestContextDetailedInformation
    {
        public IntPtr LocalizedReasonModule;
        public UInt32 LocalizedReasonId;
        public UInt32 ReasonStringCount;
        [MarshalAs(UnmanagedType.LPWStr)]
        public string[] ReasonStrings;
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    public struct POWER_REQUEST_CONTEXT_DETAILED
    {
        public UInt32 Version;
        public UInt32 Flags;
        public PowerRequestContextDetailedInformation DetailedInformation;
    }
    #endregion



    /// <summary>
    /// Prevent screensaver, display dimming and power saving. This function wraps PInvokes on Win32 API. 
    /// </summary>
    /// <param name="enableConstantDisplayAndPower">True to get a constant display and power - False to clear the settings</param>
    private void EnableConstantDisplayAndPower(bool enableConstantDisplayAndPower)
    {
        if (enableConstantDisplayAndPower)
        {
            // Set up the diagnostic string
            _PowerRequestContext.Version = POWER_REQUEST_CONTEXT_VERSION;
            _PowerRequestContext.Flags = POWER_REQUEST_CONTEXT_SIMPLE_STRING;
            _PowerRequestContext.SimpleReasonString = "Continuous measurement"; // your reason for changing the power settings;

            // Create the request, get a handle
            _PowerRequest = PowerCreateRequest(ref _PowerRequestContext);

            // Set the request
            PowerSetRequest(_PowerRequest, PowerRequestType.PowerRequestSystemRequired);
            PowerSetRequest(_PowerRequest, PowerRequestType.PowerRequestDisplayRequired);
        }
        else
        {
            // Clear the request
            PowerClearRequest(_PowerRequest, PowerRequestType.PowerRequestSystemRequired);
            PowerClearRequest(_PowerRequest, PowerRequestType.PowerRequestDisplayRequired);

            CloseHandle(_PowerRequest);
        }
    }
Guillemot answered 8/1, 2014 at 12:48 Comment(3)
This method is nice because the reasons you give for the system not sleeping etc. will show up when you run powercfg /requests. This will aid in users diagnosing sleep issuesHemorrhoid
Ironic that a site called webhost4life is dead.Stomatic
The POWER_REQUEST_CONTEXT struct should really have two extra IntPtr fields at the end to pad it out so that it is the struct is as large as the minimum size in the detailed case.Goggles
M
23

I had a problem like this with a hardware device connected via usb. XP /Vista would sleep/hibernate right in the middle of ... Great you say, when it resumes it can just continue. If the hardware is still connected!!! Users have the habit of pulling cables out whenever they feel like it.

You need to handle XP and Vista

Under XP trap the WM_POWERBROADCAST and look for the PBT_APMQUERYSUSPEND wparam.

   // See if bit 1 is set, this means that you can send a deny while we are busy
   if (message.LParam & 0x1)
   {
      // send the deny message
      return BROADCAST_QUERY_DENY;
   } // if
   else
   {
      return TRUE;
   } // else

Under Vista use SetThreadExecutionState like this

// try this for vista, it will fail on XP
if (SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED | ES_AWAYMODE_REQUIRED) == NULL)
{
   // try XP variant as well just to make sure 
   SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED);
}  // if 

and when you app has finished set it back to normal

// set state back to normal
SetThreadExecutionState(ES_CONTINUOUS);
Midst answered 10/3, 2009 at 8:6 Comment(7)
Hmm, i was wrong, SetThreadExecutionState actually did work, just had to set the ES_AWAYMODE_REQUIRED also. The strange thing is that my monitor goes black but the system never fully goes to sleep.Amphibiotic
That's what away mode is all about. The idea is that the computer would normally be sleeping, so it's made to look like it's sleeping. Then when the background task is done (e.g. recording a TV show), the app turns off the system required and away mode bits and the computer actually does go to sleep.Cartridge
>The strange thing is that my monitor goes black but the system never fully goes to sleep --- maybe that's just the default empty screen saver?Provincial
Here's a link to the Window Message to save anyone the google: msdn.microsoft.com/en-us/library/windows/desktop/…Sightseeing
Will SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED); work for WinXP?Anguiano
I'm still unclear on how ES_AWAYMODE_REQUIRED differs from ES_SYSTEM_REQUIRED.Dukedom
@AlexBudovski AFAIU ES_AWAYMODE_REQUIRED changes sleep mode to keep the CPU/system actually running, even when the user closes a laptop for instance. ES_SYSTEM_REQUIRED tells the system to stay awake without any user input.Wilmerwilmette
A
10

Using PowerCreateRequest, PowerSetRequest, and PowerClearRequest functions is the preferred method. Details and sample code (C/C#) are inside http://msdn.microsoft.com/en-us/library/windows/hardware/gg463205.aspx

Arquebus answered 18/4, 2013 at 15:3 Comment(0)
B
2

set wsc = CreateObject("WScript.Shell")

Do WScript.Sleep (60*1000) wsc.SendKeys ("{SCROLLLOCK 2}") Loop

-put the above code in notepad and save the file as .vbs and double click the file

Butcherbird answered 12/4, 2021 at 10:49 Comment(0)
C
1

The same technique applies as for preventing the screensaver should be used. See Programmatically prevent Windows screensaver from starting.

Note that some security settings can override this (forcing computers to lock after a certain time is one).

Candi answered 10/3, 2009 at 7:51 Comment(0)
H
1

If you need a display that should work until your application is running then try to set "ES_DISPLAY_REQUIRED" instead of away mode:

SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED | ES_DISPLAY_REQUIRED);

Once you are done with your application make sure to clear all other flags.

SetThreadExecutionState(ES_CONTINUOUS);
Hydrogenolysis answered 6/10, 2021 at 10:31 Comment(0)
N
0

How about waking it back up if it goes to sleep?

http://www.enterprisenetworksandservers.com/monthly/art.php?1049

Novelia answered 10/3, 2009 at 7:48 Comment(1)
Not possible, i have to disable a wifi-device before the computer goes to sleep. Otherwise the device will become unusable when i wake the computer up again. Intel is slow with win7 drivers :(Amphibiotic
S
0

Below is my attempt using the modern power availability request API (supersedes SetThreadExecutionState), as suggested by vim.

I'm using a nice P/Invoke NuGet I came across, Vanara.PInvoke.Kernel32:

using Vanara.PInvoke;
using static Vanara.PInvoke.Kernel32;

// create request object
using var request = PowerCreateRequest(new REASON_CONTEXT("App FOO is working"));
if (request.IsInvalid)
{
    throw new InvalidOperationException(
       $"Could not create power availability request: {Win32Error.GetLastError()}");
}

// send request
if (!PowerSetRequest(request, POWER_REQUEST_TYPE.PowerRequestSystemRequired))
{
    throw new InvalidOperationException(
       $"Could not send power availability request: {Win32Error.GetLastError()}");
}
    
// do stuff that required the machine to be up
Console.WriteLine("Doing stuff...");
await Task.Delay(5000);

// clear request
if (!PowerClearRequest(request, POWER_REQUEST_TYPE.PowerRequestSystemRequired))
{
    Console.WriteLine(
      "WARNING: Could not clear power availability request: {0}",
      Win32Error.GetLastError());
}

You can see your request in action by issuing powercfg /requests from an admin terminal.

Sorrow answered 28/8, 2020 at 11:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.