Skip to content

Instantly share code, notes, and snippets.

@andyneff
Last active January 18, 2021 15:24
Show Gist options
  • Save andyneff/dff921fd01214809820f4f4035ed7360 to your computer and use it in GitHub Desktop.
Save andyneff/dff921fd01214809820f4f4035ed7360 to your computer and use it in GitHub Desktop.
A script to forceable put your computer to sleep
# Basic windows GUI that will persistently try and put your computer to sleep.
# WARNING: This ignores Alt+F4 and commands to kill the app. This is on purpose.
# The only way to kill is with a force kill, which defeats the purpose of the
# script
import signal
import time
import os
import threading
import win32api
import win32con
import win32gui
os.environ['PYGAME_HIDE_SUPPORT_PROMPT'] = '1'
from pygame import mixer
INITIAL_MESSAGE = "Bedtime"
class ShutdownGui():
def __init__(self):
self.message = INITIAL_MESSAGE
self.repeat_rate = 30*60
self.done = False
self.stage_delays = [60, 15]
self.stage_filenames = ["dustyroom_sound_design_digital_descend_shutdown.mp3",
"zapsplat_science_fiction_machine_power_down_just_low_freq_44823.mp3"]
self.stage_repeats = [5, 1]
#get instance handle
hInstance = win32api.GetModuleHandle()
# the class name
className = 'SimpleWin32'
# create and initialize window class
wndClass = win32gui.WNDCLASS()
wndClass.style = win32con.CS_HREDRAW | win32con.CS_VREDRAW
wndClass.lpfnWndProc = self.wndProc
wndClass.hInstance = hInstance
wndClass.hIcon = win32gui.LoadIcon(0, win32con.IDI_APPLICATION)
wndClass.hCursor = win32gui.LoadCursor(0, win32con.IDC_ARROW)
wndClass.hbrBackground = win32gui.GetStockObject(win32con.WHITE_BRUSH)
wndClass.lpszClassName = className
wndClassAtom = win32gui.RegisterClass(wndClass)
self.window = win32gui.CreateWindow(
wndClassAtom, #it seems message dispatching only works with the atom, not the class name
'Night Night ' + os.environ['USERNAME'].title(),
win32con.WS_OVERLAPPEDWINDOW,
win32con.CW_USEDEFAULT,
win32con.CW_USEDEFAULT,
300, 100,
0,
0,
hInstance,
None)
# Show & update the window
win32gui.ShowWindow(self.window, win32con.SW_SHOWMINNOACTIVE)
win32gui.UpdateWindow(self.window)
def run(self):
win32gui.PumpMessages()
def wndProc(self, hWnd, message, wParam, lParam):
if message == win32con.WM_PAINT:
hDC, paintStruct = win32gui.BeginPaint(hWnd)
rect = win32gui.GetClientRect(hWnd)
win32gui.DrawText(hDC, self.message, -1, rect,
win32con.DT_SINGLELINE | win32con.DT_CENTER | win32con.DT_VCENTER)
win32gui.EndPaint(hWnd, paintStruct)
return 0
elif message == win32con.WM_LBUTTONUP:
self.running = False
try:
self.sleep_timer.cancel()
except:
pass
elif message == win32con.WM_CLOSE:
if self.done:
return win32gui.DefWindowProc(hWnd, message, wParam, lParam)
print('No closing!')
elif message == win32con.WM_DESTROY:
win32gui.PostQuitMessage(0)
return 0
elif message == win32con.WM_POWERBROADCAST:
if wParam == win32con.PBT_APMSUSPEND: # Going to sleep
# If the user preemptively sleeps, then kill this script
self.done = True
win32gui.PostMessage(self.window, win32con.WM_CLOSE, 0, 0)
else:
return win32gui.DefWindowProc(hWnd, message, wParam, lParam)
def sleep(self, secs):
self.sleep_timer = threading.Timer(secs, lambda: None)
self.sleep_timer.start()
self.sleep_timer.join()
def redraw(self):
win32gui.RedrawWindow(self.window, None, None,
win32con.RDW_ERASE | win32con.RDW_INVALIDATE)
def shutdown_timer(self):
mixer.init()
mixer.music.set_volume(0.3)
while 1:
self.running = True
self.shutdown()
self.message = "Resume at " + \
time.strftime('%H:%M.%S',
time.localtime(time.time() + self.repeat_rate))
self.redraw()
self.sleep(self.repeat_rate)
def shutdown(self):
# for stage in range(len(self.stage_delays)):
for stage in range(len(self.stage_delays)):
mixer.music.load(self.stage_filenames[stage])
for x in range(self.stage_repeats[stage]):
self.message = f'Stage {stage+1} of {len(self.stage_delays)} ({x+1}/{self.stage_repeats[stage]})'
self.redraw()
mixer.music.play()
self.sleep(self.stage_delays[stage])
if not self.running:
return
if self.running:
self.done = True
os.system('shutdown /h')
win32gui.PostMessage(self.window, win32con.WM_CLOSE, 0, 0)
def main():
gui = ShutdownGui()
threading.Thread(target=gui.shutdown_timer, daemon=True).start()
gui.run()
# Only works if ShowWindow is called
def exit_app(signum, frame):
win32gui.PostQuitMessage(0)
if __name__ == '__main__':
signal.signal(signal.SIGINT, exit_app)
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment