Python SetThreadExecutionState: How do I prevent screen display from turning off? - python

I am on Windows. I want to run a Python Script that involves keyboard activity hence my PC mustn't lock screen or go to sleep. Instead of changing my PC Sleep Setting, I want to use Python code to keep my Screen Display On for the whole duration of my Python Script.
I modified the code here Prevent sleep mode python (Wakelock on python) but it doesn't work. My screen display still offs automatically. MY modified code as below:
class WindowsInhibitor:
'''Prevent OS sleep/hibernate in windows; code from:
https://github.com/h3llrais3r/Deluge-PreventSuspendPlus/blob/master/preventsuspendplus/core.py
API documentation:
https://msdn.microsoft.com/en-us/library/windows/desktop/aa373208(v=vs.85).aspx'''
ES_CONTINUOUS = 0x80000000
ES_SYSTEM_REQUIRED = 0x00000001
ES_DISPLAY_REQUIRED= 0x00000002
def __init__(self):
pass
def inhibit(self):
import ctypes
print("Preventing Windows from going to sleep")
ctypes.windll.kernel32.SetThreadExecutionState(
WindowsInhibitor.ES_CONTINUOUS | \
WindowsInhibitor.ES_DISPLAY_REQUIRED)
def uninhibit(self):
import ctypes
print("Allowing Windows to go to sleep")
ctypes.windll.kernel32.SetThreadExecutionState(
WindowsInhibitor.ES_CONTINUOUS)
import os
osSleep = None
# in Windows, prevent the OS from sleeping while we run
if os.name == 'nt':
osSleep = WindowsInhibitor()
osSleep.inhibit()

Related

Why my app keep opening when I use shortcut in Python?

I tried to create a program to open a app with a specific shortcut but when I press my keys it keep opening and didn't stop until I stopped the program
import keyboard
import time
import subprocess
while True:
if keyboard.is_pressed('ctrl+space+b'):
subprocess.Popen([r"C:\\Program Files\\Everything\\Everything.exe"])
time.sleep(1.5)
How about try this code
import keyboard
import subprocess
import threading
def run_my_program():
subprocess.run([r"C:\Program Files\Everything\Everything.exe"])
while True:
if keyboard.is_pressed('ctrl+space+b'):
threading.Thread(target=run_my_program).start() # launch up the subprocess in parallel so input is not delayed
while keyboard.is_pressed('ctrl+space+b'):
pass # Wait until user lifts his hands off the keyboard

Waiting for user input when controlling 3rd party application via python script

I am writing a script intended to be used by members of a project team. As part of the script, I am launching a 3rd party proprietary application run through Citrix. I am going to use the script mostly to send keys to this application, but the first step once it launches is for the user to log in.
Because I would like the user to log in while the script is running, rather than asking for user/pass from some kind of GUI input earlier, and because the time it takes Citrix to launch varies, I would like to include some kind of logic that detects when the user has logged in and then resume the script from there, rather than including an obnoxiously long implicit wait or risking the script timing out.
Is there a way to detect user keystrokes using win32com.client (or to detect a change in state of the application itself)? See below for the relevant code to launch the app:
import win32com.client
shell = win32com.client.Dispatch("WScript.Shell")
shell.Run('C:\Citrix\[rest of path])
EDIT:
Per Vasily's suggestion in the comments below, I attempted to adapt the "hook and listen" code to my scenario, but was unsuccessful. When I launch my file, I don't even get an exception message in my terminal, I get a Windows pop-up that says Python encountered a problem and needs to quit.
This is how I adapted it:
#[omitting import lines for brevity]
def on_timer():
"""Callback by timer out"""
win32api.PostThreadMessage(main_thread_id, win32con.WM_QUIT, 0, 0);
def on_event(args):
"""Callback for keyboard and mouse events"""
if isinstance(args, KeyboardEvent):
for i in range(1,100):
time.sleep(1)
if args.pressed_key == 'Lcontrol':
break
def init():
hk = Hook()
hk.handler = on_event
main_thread_id = win32api.GetCurrentThreadId()
t = Timer(55.0, on_timer) # Quit after 55 seconds
t.start()
hk.hook(keyboard=True, mouse=True)
At the point when the 3rd party Citrix app begins to launch in my main script, I call hookandlisten.init().
As a reminder, my goal is to wait until the user sends a certain keystroke (here I chose Control) before proceeding with the rest of the main script.
Solved this by eliminating the timer and unhooking the keyboard upon the correct keystroke:
import win32api
import win32con
from pywinauto.win32_hooks import Hook
from pywinauto.win32_hooks import KeyboardEvent
from pywinauto.win32_hooks import MouseEvent
def on_event(args):
"""Callback for keyboard and mouse events"""
if isinstance(args, KeyboardEvent):
if args.current_key == 'Lcontrol' and args.event_type == 'key down':
print("Success")
hk.unhook_keyboard()
return
def init():
hk.handler = on_event
hk.hook(keyboard=True, mouse=False)
hk = Hook()

Make script executable on OSX?

I wrote a little script in python, it basically open a VPN program and then it open a new window in firefox and log in a website. I would like now to avoid launching it from the terminal, and be able to make double click on it(is it called an executable file?). How can I achieve this? I work with python 2.7 on a mac 10.11.1.
I am sorry for eventual mistake but programming is still quite new for me!
import webbrowser
from Quartz.CoreGraphics import *
import subprocess as sp
import time
import pyautogui
def mouseEvent(type, posx, posy):
theEvent = CGEventCreateMouseEvent(None, type, (posx,posy),
kCGMouseButtonLeft)
CGEventPost(kCGHIDEventTap, theEvent)
def mousemove(posx,posy):
mouseEvent(kCGEventMouseMoved, posx,posy);
def mouseclick(posx,posy):
mouseEvent(kCGEventLeftMouseDown, posx,posy);
mouseEvent(kCGEventLeftMouseUp, posx,posy);
# opening strong VPN
xfoil = sp.Popen(['open', '-a', '/Applications/StrongVPN Client.app'], stdin=sp.PIPE, stdout=sp.PIPE)
time.sleep(5)
mouseclick(900,360);
time.sleep(1)
#open firefox and going to skygo
b = webbrowser.get('firefox')
b.open('http://skygo.sky.it/index.shtml')
time.sleep( 5 )
mouseclick(1010,225);
#clicking on login;
mouseclick(1074,123);
time.sleep( 5 )
mouseclick(830,225);
time.sleep(2)
pyautogui.typewrite('myusername')
time.sleep(1)
#inserting password
mouseclick(830,290);
time.sleep(2)
pyautogui.typewrite('mypassword')
time.sleep(1)
#pressing enter
mouseclick(920,400);
time.sleep(2)
#mousemove(int(currentpos.x),int(currentpos.y)); # Restore mouse position
You can use Automator to wrap a Python script to a normal Mac App bundle that can be opened from OSX GUI.
Better still, what you are trying to achieve can be probably better implemented as set of action in Automator without having to write any Python scripts.

How to treat "Quit" event in python, on Mac OS

I need to detect when the user pressed "quit" in the dock menu.
My application is actually just a launcher for the backend server of a web interface. I keep it in the dock menu by manually waiting for the launched process to end (with poll and sleep). The actvity monitor showed it as not responding so I added a native function to process events like "touches". Not responding flag is now gone, but the user cannot quit this application (because the native functions processes the event, I guess).
I used ctypes to access that native function.
TVB = subprocess.popen(args)
coreFoundation = cdll.LoadLibrary('/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation')
CFRunLoopRunInMode = coreFoundation.CFRunLoopRunInMode # the native function
CFRunLoopRunInMode.restype = c_int32 # its return type
CFRunLoopRunInMode.argtypes = [ c_void_p, c_double, c_bool ] # its arguments types
defaultMode = c_void_p.in_dll(coreFoundation, u'kCFRunLoopDefaultMode') # the default mode to process events
sleepTime = c_double(5) # the duration to process the events
retAfterSourceHandled = c_bool(0) # do NOT return after processing
while not TVB.poll(): # keep alive as long as TVB is alive
CFRunLoopRunInMode(defaultMode, sleepTime, retAfterSourceHandled)
sleep(5)
#detect 'quit' here and stop TVB, then quit
I will also consider other solutions to CFRunLoopRunInMode... Something like processNextEvent() would be ideal.
A possible solution to this problem is to use PyObjC and a custom UIApplicationDelegate implementation.
import AppKit
import Foundation
from PyObjCTools import AppHelper
class ApplicationDelegate(Foundation.NSObject):
""" MAC OS UI specific Delegate class """
def applicationDidFinishLaunching_(self, notification):
""" Here you could register a timer to pull your sub-processes, for example. """
pass
def applicationWillTerminate_(self, notification):
""" This is the hook you get for when the user clicks QUIT in dock """
pass
app = AppKit.NSApplication.sharedApplication()
delegate = ApplicationDelegate.alloc().init()
app.setDelegate_(delegate)
AppHelper.runEventLoop()
In the end PyObjC is not much different than the ctypes loads you tried, but it has some helper methods (like AppKit.NSRunLoop.currentRunLoop(), or AppHelper.stopEventLoop()) which could make the python code clearer.
For this solution I assume to have a Python project further packed for deployment with py2app. I used pyObjc version 2.3 (installed with easy_install in Python 2.7 on Mac OS x 10.7.5).

How to prevent a script being stopped by suspend?

I have a python alarm clock script, which needs to wake me up at some time.When I go to bed and leave it running, the laptop I use which has Linux Mint suspends itself after some time of inactivity.How can I prevent my script from being stopped and keep it running? My laptop is in my room and I need to close its lid because its light is annoying to sleep to.Here is my script.
import time
import sys
import webbrowser
alarm_HH = raw_input("Enter the hour you want to wake up at\n")
alarm_MM = raw_input("Enter the minute you want to wake up at\n")
print("You want to wake up at ", alarm_HH)
while True:
now = time.localtime()
if now.tm_hour == int(alarm_HH) and now.tm_min == int(alarm_MM):
webbrowser.open_new_tab("http://www.repeatmyvids.com/watch?v=SXLplRtMNfg&kmdom=youtube")
break
else:
timeout = 60 - now.tm_sec
if raw_input("Want me to stop?"):
break
[EDIT]
Ok so I figured it out.I installed python xlib module, which is a low level python library that you can install with sudo aptitude install python-xlib.I added a few lines of code that move the mouse pointer in order to prevent suspend, or sleep, so that my script can still work with lid closed and no input from anywhere.
d = display.Display()
s = d.screen()
root = s.root
root.warp_pointer(500,500)
d.sync()
I added a few of these, and the code now looks like this.
import time
import sys
import webbrowser
from Xlib import X, display
alarm_HH = input("Enter the hour you want to wake up at\n")
alarm_MM = input("Enter the minute you want to wake up at\n")
print("You want to wake up at ", alarm_HH)
while True:
now = time.localtime()
if now.tm_hour == int(alarm_HH) and now.tm_min == int(alarm_MM):
webbrowser.open_new_tab("http://www.repeatmyvids.com/watch?v=SXLplRtMNfg&kmdom=youtube")
break
else:
d = display.Display()
s = d.screen()
root = s.root
root.warp_pointer(500,500)
d.sync()
time.sleep( 5 )
root.warp_pointer(250,250)
d.sync()
time.sleep( 5 )
root.warp_pointer(100,100)
d.sync()
time.sleep( 5 )
root.warp_pointer(250,250)
d.sync()
Thanks to EngHamoud for giving me the idea to move the pointer in order to prevent suspend.
will if terminated because the script itself you could use the atexit
http://docs.python.org/2/library/atexit.html
if it's suspend because of the operating system "after period of time that the user haven't been active " i had faced that problem before then i've used the module xlib to control my mouse to move it randomly to it will be active
otherwise i think you gotta figure out the correct for your os configuration
hopefully i've answered what you've wondered about
Even in sleep mode S1 (your "suspend" I think), the CPU(s) stop executing instructions. So your program is no longer running -- hence cannot wake-up your computer...
You will certainly have to explore other ways of doing, such as configuring the real-time clock (which is still powered at sleep) to wake-up the computer. On embedded systems, you also have access to an hardware watchdog that could be (miss)used for that purpose. Don't know if this is available on PC.
The mouse trick appears to work in Windows too if you want to prevent suspension of your program after leaving it "idle" for a long time. It's doesn't appear to prevent the OS from sleeping though and pausing it that way :( Here's my asynchronous Windows solution using the mouse move concept:
Create one of these KeepActiveThread objects, and call start() / stop() as needed when you have a really long running processes.
import win32api # pywin32
import thread
import time
OSCILLATION_FREQ_SECS = 30
class KeepActiveThread() :
def __init__( self ) :
self.activeId_ = None
self.resurrectId_ = None
def start( self ) :
if self.activeId_ is None :
if self.resurrectId_ is None :
self.resurrectId_ = thread.start_new_thread(
self.__oscillateMouseCursor, () )
self.activeId_ = self.resurrectId_
def stop( self ) :
self.activeId_ = None
def __oscillateMouseCursor( self ) :
move = 1
while self.activeId_ :
move *= -1
try:
(x, y) = win32api.GetCursorPos()
win32api.SetCursorPos( (x+move, y) )
except: pass
time.sleep( OSCILLATION_FREQ_SECS )
self.resurrectId_ = None
I recomend using ctypes:
import ctypes
ES_CONTINUOUS = 0x80000000
ES_SYSTEM_REQUIRED = 0x00000001
ctypes.windll.kernel32.SetThreadExecutionState(
ES_CONTINUOUS | \
ES_SYSTEM_REQUIRED)

Categories