Using Sikuli to take automated screenshots of a window? - python

Simple question here: I'd like to use Sikuli to take a screenshot of a window on a mac, which would be done by hitting CMD+SHIFT+4 then hitting Space, then clicking a window.
For the CMD+SHIFT+4 I'm having trouble. This doesn't work:
keyDown(KEY_META)
keyDown(Key.SHIFT)
wait(1)
type("4")
wait(1)
keyUp(Key.SHIFT)
keyUp(KEY_META)
Anyone have any ideas? I'm open to other routes of hitting the key combo, for instance, I know to copy this works well:
type("c",KEY_META)
But, it doesn't accept three arguments.

type("4", KeyModifier.CMD+KeyModifier.SHIFT)
Or, even better:
import shutil
import os
screenshotsDir = "absolute-path-to-a-folder"
img = capture(some_region)
shutil.move(img, os.path.join(screenshotsDir, "some-name.png"))
where some_region is:
some_region = SCREEN # for whole screen
or
someRegion = App.focusedWindow() # for the frontmost window
This has the advantage, that you can control the file name of the shot.

Have found a better solution, which actually works:
screen = Screen()
scr_img = screen.capture(screen.getBounds())
scr_img.save("C:\Screenshots", "screenshot")
Screen.capture() returns an instance of ScreenImage class with methods:'save', 'saveInBundle', 'getFile', 'getFilename'. The method save() adds an unique number to a supplied prefix parameter.

Related

pywinauto with a popup window

Im working through pywinauto, not a great developer but I can write some of the basics in python. Im getting hung up though. I have a popup that is causing me to not be able to press ok on and really not sure what direction I need to look
Really a two part question:
How can I move over to this popup IF it occurs, this wont always be the case as sometimes those files may not exist.
I tried using app.Confirm.Ok.click() and also app.Confirm.type('{ENTER}') neither worked.
How can I add in variables that I could call from an external .txt file for things like the "localhost" I included there in my code?
Code here:
from pywinauto import application
import time
app = application.Application()
app.start("Install.exe")
app.SelectLanguage.Ok.click()
app.Platform.Iacceptthetermsinthelicenseagreement.click()
app.Platform.Next.click()
app.Platform.Next.click()
app.PlatformInstallationOptions.Next.click()
app.PlatformSpecifyCertifcate.comboBox.select(0)
app.PlatformSpecifyCertifcate.Next.click()
app.PlatformConfigurationDatabaseOptions.type_keys('{TAB}')
app.PlatformConfigurationDatabaseOptions.type_keys('{TAB}')
app.PlatformConfigurationDatabaseOptions.type_keys('localhost')
app.PlatformConfigurationDatabaseOptions.type_keys('{TAB}')
app.PlatformConfigurationDatabaseOptions.type_keys('{SPACE}')
app.PlatformConfigurationDatabaseOptions.type_keys('{TAB}')
app.PlatformConfigurationDatabaseOptions.type_keys('Config')
app.PlatformConfigurationDatabaseOptions.Next.click()
app.PlatformSpecifyHTTPSBindingCertifcate.type_keys('{TAB}')
app.PlatformSpecifyHTTPSBindingCertifcate.type_keys('{TAB}')
app.PlatformSpecifyHTTPSBindingCertifcate.type_keys('{RIGHT}')
app.PlatformSpecifyHTTPSBindingCertifcate.type_keys('{SPACE}')
app.PlatformSpecifyHTTPSBindingCertifcate.Next.click()
app.PlatformAdvancedWorkflowSettings.Next.click()
app.PlatformPlatformLanguage.Next.click()
app.PlatformInstanceDatabaseOptions.type_keys('{TAB}')
app.PlatformInstanceDatabaseOptions.type_keys('{TAB}')
app.PlatformInstanceDatabaseOptions.type_keys('localhost')
app.PlatformInstanceDatabaseOptions.type_keys('{TAB}')
app.PlatformInstanceDatabaseOptions.type_keys('{SPACE}')
app.PlatformInstanceDatabaseOptions.type_keys('{TAB}')
app.PlatformInstanceDatabaseOptions.type_keys('Instance')
app.PlatformInstanceDatabaseOptions.Next.click()
app.PlatformTimeZone.Next.click()
app.WebApplicationOptions.type_keys('{TAB}')
app.WebApplicationOptions.type_keys('{TAB}')
app.WebApplicationOptions.type_keys('{TAB}')
app.WebApplicationOptions.type_keys('{TAB}')
app.WebApplicationOptions.type_keys('{UP}')
app.WebApplicationOptions.Next.click()
app.WebApplicationOptions.type_keys('{ENTER}')
confirmWin = .app.window(title_re = u'Confirm') #Check your window header object name.
# Use timeout based on average pop up time in your application.
if confirmWin.exists(timeout=10, retry_interval=1):
confirmWin.set_focus()
yesBtn = confirmWin[u'&Yes']
# Check the object name of the Yes button. You can use Swapy tool(It is deprecated but it works, else you can use inspect.exe)
yesBtn.click()
else:
print('Confirmation pop up did not appear')
This should work :)

How do I make a window (already running task) visible using pywinauto?

Besides looking for answers on this site, I checked out
pywinauto.application module
and
Getting Started Guide
but I'm still stumped.
I manually start notepad and want the first while block of the following code to make the notepad window visible. The second while block works but I am confused about the line
dlg_spec = app.UntitledNotepad
What is going on here? What kind of a python method is this?
Question: How do I get the first while block of code make the window titled
Untitled - Notepad
visible?
#--------*---------*---------*---------*---------*---------*---------*---------*
# Desc: Set focus on a window
# #--------*---------*---------*---------*---------*---------*---------*---------*
import sys
import pywinauto
# # Manually started Notepad
# # Want to make it visible (windows focus)
# # Program runs, but...
while 1:
handle = pywinauto.findwindows.find_windows(title='Untitled - Notepad')[0]
app = pywinauto.application.Application()
ac = app.connect(handle=handle)
print(ac)
topWin = ac.top_window_()
print(topWin)
sys.exit()
# # Working Sample Code
while 0:
app = pywinauto.Application().start('notepad.exe')
# describe the window inside Notepad.exe process
# # ?1: '.UntitledNotepad' - huh?
dlg_spec = app.UntitledNotepad
# wait till the window is really open
actionable_dlg = dlg_spec.wait('visible')
sys.exit()
For convenience this code does the trick:
# # Manually started Notepad
# # Want to make it visible (windows focus).
# #
# # Two or three lines solution provided by
# # Vasily Ryabov's overflow answer
# # (wrapper ribbon and bow stuff).
while 1:
app = pywinauto.application.Application().connect(title="Untitled - Notepad")
dlg_spec = app.window(best_match="UntitledNotepad")
dlg_spec.set_focus()
sys.exit()
I would suggest you using the win32gui library for this task as shown below:
import win32gui
hwnd = win32gui.FindWindow(None, 'Notepad')
win32gui.SetForegroundWindow(hwnd)
win32gui.ShowWindow(hwnd, 9)
The number 9 represents SW_RESTORE as shown here
Well, the first while loop should be re-written using the same methods except find_windows (it's low level and not recommended for direct usage). You need method .set_focus() to bring the window to foreground.
app = pywinauto.Application().connect(title="Untitled - Notepad")
app.UntitledNotepad.set_focus()
Creating window specification dlg_spec = app.UntitledNotepad means that app method __getattribute__ is called. Finally this line is equivalent to dlg_spec = app.window(best_match="UntitledNotepad"). To find the actual wrapper you need to call .wait(...) or .wrapper_object().
But when you call an action (like .set_focus()), Python can do the wrapper_object() call for you implicitly (while accessing attribute set_focus dynamically).

Is it possible to ignore dialogue boxes when checking size of focused window?

I noticed that if using windows focus detection, the rect value will change depending on what part of the program you are in. I want the size of the main window only if possible.
I've managed to get around some of these issues by checking the window title. If the title is empty, it's a dropdown menu, so ignore. If it is titled "Open", "Save As", etc, then it's obviously a dialogue box and ignore. However, the message "Do you want to quit without saving?" seems to have only the title of the program itself, so that slips through the check.
I just tested the heights of those boxes to see if there was a constant value to ignore, but each program seems to have different heights. I could possibly just ignore anything under a certain resolution, but I'd prefer not to as it's not actually solving the issue, and there may be some rare cases where it needs to use that particular resolution.
Here's the bits of code I currently use from pywin32 to do the detection. I also have the ctypes alternatives, but it's basically the same thing.
import win32gui
import win32process
import psutil
hwnd = win32gui.GetForegroundWindow()
print 'pid:', win32process.GetWindowThreadProcessId(hwnd)[1]
print 'rect:', win32gui.GetWindowRect(hwnd)
print 'name:', win32gui.GetWindowText(hwnd)
print 'exe:', psutil.Process(win32process.GetWindowThreadProcessId(hwnd)[1]).name()
Basically I want the size of the main window at all times, no matter which other windows are loaded on top of it. I've only found GetWindowRect and GetClientRect which both do the same thing, just wondering if I'm missing something?
Managed to get to the solution by realising it was basically the last parent window I needed:
def _get_parent(self):
while True:
try:
parent = win32gui.GetParent(hwnd)
except UnboundLocalError:
hwnd = win32gui.GetForegroundWindow()
else:
if parent:
hwnd = parent
else:
break
return hwnd
Basically it just keeps checking if the current window has a parent until there are no more parents. Not super efficient but does the job. I've only really tested it on paint > save as > are you sure you want to replace?, but it gets the correct hwnd value for the main window and returns a constant resolution.

Creating GUI for a simple python script

I have this little script that counts how many words there are in a file and how many times a word repeats. I want to make a gui in wxPython in which i can enter the filename and it will show me the result.
I've been looking at wxPython examples but still haven't got the hang of it. Here's the script
#!/usr/bin/env python
import sys
import os
import re
import operator
if len(sys.argv) == 1:
sys.exit("Usage: "+sys.argv[0]+" files...");
line = sys.argv[1:]
num = 0
dic = {}
for i in line:
dat = open(i, "r").read()
words = re.findall(r'[a-z]+',dat)
for word in words:
if len(word)>3:
num=num+1
if dic.has_key(word):
dic[word]=dic[word]+1
else:
dic[word]=1
print num
sorted_dic = sorted(dic.iteritems(), key=operator.itemgetter(1), reverse=True)
print sorted_dic
Take a look at wx.FileDialog to get you started. Here's a tutorial that talks about all the standard dialogs, including the file dialog: http://www.blog.pythonlibrary.org/2010/06/26/the-dialogs-of-wxpython-part-1-of-2/ (scroll down about half-way).
Now you'll probably open the file dialog with some sort of button. So you bind the button to EVT_BUTTON and open the file dialog in the event handler. Something like this:
myButton.Bind(wx.EVT_BUTTON, self.openFileDialog)
Now in your openFileDialog (event handler) method, you can open the dialog and retrieve the path. At this point, you pass the path to the code you've already written which can be a part of the event handler or you could put it in its own method. Then when you get the result, you would probably want to display it in a wx.StaticText widget or perhaps show it in a wx.MessageBox
It's not clear what your question is, what part of the GUI (That isn't shown here) are you having trouble with? Instead of wxPython, check out tkinter. In tkinter, you can use the tkFileDialog and get the filepath of the file you want to open and parse, although wxPython has similar funcitonality.
I don't want to write out the code for you, but basically, it'll require:
Create a frame,
Create the button that'll be bound to the command that'll launch the tkFileDialog
Another set of widgets that'll be bound to the command that'll count the words in the file
Display your results somehow.

Renaming windows with python Xlib

Using the Xlib module for python, I have managed to move, resize, and destroy windows by calling configure() and destroy() respectively followed by display.sync().
However, I can't seem to rename existing windows. The following code outputs 'foo':
window.set_wm_name('foo')
window.set_wm_icon_name('foo')
print window.get_wm_name()
which would suggest that the object updates properly. On my screen, though, the window's title doesn't change at all, even after calling display.sync(). Am I using the set_wm_name functions correctly, if they should be used at all for this sort of task?
I know im extremly late with this answer but maybe someone will find it usefull
from Xlib.display import Display
from Xlib.Xatom import STRING
display = Display()
root = display.screen().root
#view the current WM_NAME
a = root.get_full_property(display.intern_atom('_NET_WM_NAME'), STRING)
print a.value
#Actualy change WM_NAME
root.change_property(display.intern_atom('_NET_WM_NAME'), STRING, 8, ' MyApp')
#read the name again
b = root.get_full_property(display.intern_atom('_NET_WM_NAME'), STRING)
print b.value
I've been unable to get window.get_wm_name()...Im sure im doing something wrong, but this works just as well :)

Categories

Resources