Last active
February 27, 2026 22:54
-
-
Save santisq/6898fcdab5af97fab0c8c03881b72260 to your computer and use it in GitHub Desktop.
SetThreadExecutionState... keeps your powershell script running without going to sleep
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System; | |
| using System.ComponentModel; | |
| using System.Runtime.InteropServices; | |
| public static class Native | |
| { | |
| private static EXECUTION_STATE? s_prevState; | |
| private const uint INPUT_KEYBOARD = 1; | |
| private const uint KEYEVENTF_KEYUP = 0x0002; | |
| [DllImport("kernel32.dll", SetLastError = true, EntryPoint = "SetThreadExecutionState")] | |
| private static extern EXECUTION_STATE SetThreadExecutionStateNative(EXECUTION_STATE esFlags); | |
| [DllImport("user32.dll", SetLastError = true)] | |
| private static extern uint SendInput(uint nInputs, INPUT[] pInputs, int cbSize); | |
| [Flags] | |
| public enum EXECUTION_STATE : uint | |
| { | |
| ES_AWAYMODE_REQUIRED = 0x00000040, | |
| ES_CONTINUOUS = 0x80000000, | |
| ES_DISPLAY_REQUIRED = 0x00000002, | |
| ES_SYSTEM_REQUIRED = 0x00000001, | |
| } | |
| [StructLayout(LayoutKind.Sequential)] | |
| private struct INPUT | |
| { | |
| public uint type; | |
| public InputUnion u; | |
| } | |
| [StructLayout(LayoutKind.Explicit)] | |
| private struct InputUnion | |
| { | |
| [FieldOffset(0)] public KEYBDINPUT ki; | |
| [FieldOffset(0)] private MOUSEINPUT dummyMouse; | |
| } | |
| [StructLayout(LayoutKind.Sequential)] | |
| private struct KEYBDINPUT | |
| { | |
| public ushort wVk; | |
| public ushort wScan; | |
| public uint dwFlags; | |
| public uint time; | |
| public UIntPtr dwExtraInfo; | |
| } | |
| [StructLayout(LayoutKind.Sequential)] | |
| private struct MOUSEINPUT | |
| { | |
| public int dx; | |
| public int dy; | |
| public uint mouseData; | |
| public uint dwFlags; | |
| public uint time; | |
| public UIntPtr dwExtraInfo; | |
| } | |
| public static void SendShiftF15() | |
| { | |
| var inputs = new INPUT[4] | |
| { | |
| CreateKeyEvent(VirtualKeyCode.ShiftLeft, 0), | |
| CreateKeyEvent(VirtualKeyCode.F15, 0), | |
| CreateKeyEvent(VirtualKeyCode.F15, KEYEVENTF_KEYUP), | |
| CreateKeyEvent(VirtualKeyCode.ShiftLeft, KEYEVENTF_KEYUP) | |
| }; | |
| uint result = SendInput((uint)inputs.Length, inputs, Marshal.SizeOf<INPUT>()); | |
| if (result != (uint)inputs.Length) throw new Win32Exception(); | |
| } | |
| private static INPUT CreateKeyEvent(ushort vk, uint flags) | |
| => new() | |
| { | |
| type = INPUT_KEYBOARD, | |
| u = new InputUnion | |
| { | |
| ki = new KEYBDINPUT | |
| { | |
| wVk = vk, | |
| wScan = 0, | |
| dwFlags = flags, | |
| time = 0, | |
| dwExtraInfo = UIntPtr.Zero | |
| } | |
| } | |
| }; | |
| private static class VirtualKeyCode | |
| { | |
| public const ushort ShiftLeft = 0xA0; | |
| public const ushort F15 = 0x7E; | |
| } | |
| public static void SetThreadExecutionState(EXECUTION_STATE esFlags) | |
| { | |
| if (esFlags.HasFlag(EXECUTION_STATE.ES_AWAYMODE_REQUIRED) | |
| && !esFlags.HasFlag(EXECUTION_STATE.ES_CONTINUOUS)) | |
| { | |
| throw new ArgumentException("ES_AWAYMODE_REQUIRED must be used with ES_CONTINUOUS."); | |
| } | |
| EXECUTION_STATE previousState = SetThreadExecutionStateNative(esFlags); | |
| if (previousState == 0) throw new Win32Exception(); | |
| s_prevState = previousState; | |
| } | |
| public static void Restore() => SetThreadExecutionState(s_prevState ?? EXECUTION_STATE.ES_CONTINUOUS); | |
| public static void PreventSleepAndDisplayOff() | |
| => SetThreadExecutionState( | |
| EXECUTION_STATE.ES_SYSTEM_REQUIRED | | |
| EXECUTION_STATE.ES_DISPLAY_REQUIRED | | |
| EXECUTION_STATE.ES_CONTINUOUS); | |
| public static void KeepAwake() | |
| { | |
| using System.Timers.Timer timer = new(TimeSpan.FromSeconds(50)) | |
| { | |
| AutoReset = true | |
| }; | |
| timer.Elapsed += (s, e) => SendShiftF15(); | |
| timer.Start(); | |
| Console.WriteLine("Keeping awake (Shift+F15 every 50s). Press any key to exit..."); | |
| Console.ReadKey(true); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment