Skip to content

Instantly share code, notes, and snippets.

@santisq
Last active February 27, 2026 22:54
Show Gist options
  • Select an option

  • Save santisq/6898fcdab5af97fab0c8c03881b72260 to your computer and use it in GitHub Desktop.

Select an option

Save santisq/6898fcdab5af97fab0c8c03881b72260 to your computer and use it in GitHub Desktop.
SetThreadExecutionState... keeps your powershell script running without going to sleep
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