How to hide COM object Dispatched from Python - python

I'm using COM in Python and I want the object to run in background - hidden.
With Excel I do:
Import win32com.client
Excel=win32com.client.Dispatch("Excel.Application")
Excel.Visible=1
but my application do not have property .Visible - is there any other way to hide it? Maybe some special parameter to Dispatch?
Thanks in advance
R

If you know your application title or class, you can hide it via ShowWindow:
import win32com.client
import win32con
import win32gui
import time
print "Start"
excel = win32com.client.Dispatch("Excel.Application")
excel.Visible = 1 # Visible via automation
time.sleep(2)
hwnd = win32gui.FindWindow(None, "Microsoft Excel") # Class or title
print "Hide"
win32gui.ShowWindow(hwnd, win32con.SW_HIDE) # Hide via Win32Api
time.sleep(2)
print "Show"
win32gui.ShowWindow(hwnd, win32con.SW_SHOW) # Show via Win32Api
time.sleep(2)
###
HTH,
Pablo

Related

Python - How to interact with system tray popup

I want to autologin to an app via its system tray icon.
I use the pywinauto module to interact with the tray icon to launch the app and now I have a popup who ask me to log on.
But... I don't know how to interact with it !
This is my icon :
Tray Icon
Here, an extract of my code (works fine) :
_pApp = Application().connect(path='my_app_dir')
taskbar.ClickSystemTrayIcon(1)
_pApp.PopupMenu.menu_item('submenu').click_input()
_pApp.PopupMenu.menu_item('another_submenu').click_input()
How can I interact with the popup authentication window below ?
Popup window
Thanks for your help.
I finally found a solution with pywinauto.keyboard. I don't know if it's clean but it works.
from pywinauto.keyboard import *
[...]
send_keys(_user)
send_keys("{VK_TAB}")
send_keys(_pass)
send_keys("{ENTER}")
Finally, I found exactly the expected behavior :)
Thank you Vasily Ryabov ! Your method is very helpful !
I do not use 'send_keys' anymore.
from tkinter.messagebox import *
from pywinauto import taskbar
from pywinauto.application import Application
[...]
_user = "TOTO"
_pass = "TOTOPASS"
app_dir = r'C:\Program Files\Common Files\App\App.exe'
icon_list = list()
# Getting the name of the icons in the sys tray
for i in range(0, 13):
app_sti = taskbar.SystemTrayIcons.wrapper_object()
app_stv = pulse_sti.button(i).info.text
icon_list.append(app_stv)
# Looking for my app name
try:
if "App_name" in str(icon_list):
app = Application().connect(path=app_dir)
taskbar.ClickSystemTrayIcon("App name")
app.PopupMenu.menu_item('menu').click_input()
app.PopupMenu.menu_item('menu -> submenu').click_input()
app_auth = Application(backend="uia").connect(title_re="Title*", timeout=5)
app_auth_window = app_auth.window(title_re="Title*")
app_auth_window.child_window(title="User :", control_type="Edit").set_text(_user)
app_auth_window.child_window(title="Password :", control_type="Edit").set_text(_pass)
app_auth_window.child_window(title="Connect", control_type="Button").click()
except Exception as error:
showwarning("Error", "App not found !")
Currently, I re-write a part of my code :
from pywinauto import taskbar
from pywinauto.application import Application
from pywinauto.keyboard import *
from tkinter.messagebox import *
[...]
app_dir = r'C:\Program Files\Common Files\App\App.exe'
_user = "TOTO"
_pass = "TOTOPASS"
# Check if my app has its system tray icon in the taskbar
for i in range(0, 10):
tsIcon = taskbar.SystemTrayIcons.wrapper_object()
tsValue = tsIcon.button(i).info.text
# If I find it, the code click on it and its menu until the popup auth window come
if "App_name" in tsValue:
_pApp = Application().connect(path=app_dir)
taskbar.ClickSystemTrayIcon(i)
_pApp.PopupMenu.menu_item('menu').click_input()
_pApp.PopupMenu.menu_item('menu->submenu').click_input()
time.sleep(2)
# When the popup window comes out, I run 'send_keys'
send_keys(_user)
send_keys("{VK_TAB}")
send_keys(_pass)
send_keys("{ENTER}")
else:
showwarning("Error", "App not found !")
[...]
My code seems good ? There is another "most clean" method ?
Thanks

Pygtk WebKit get source html

Here is my sample code. How do I get the html source code of the current page. It only prints 'GString at 0x8875130' . How to convert it to real text contains html?
from gi.repository import WebKit
from gi.repository import Gtk, Gdk
def get_source(webobj, frame):
print "loading..."
x = web.get_main_frame().get_data_source().get_data()
print x
win = Gtk.Window()
web = WebKit.WebView()
web.open("http://google.com")
web.connect("load-finished", get_source)
win.add(web)
win.show_all()
Gtk.main()
print x.str
Data is available as .str member of GLib.String object. For further details try help(GLib.String) on python prompt after importing libraries.
#Before you can use the require_version() method from gi, you need to import the gi module.
import gi
#Specify versions to import from the repository.
gi.require_version('Gtk','3.0')
gi.require_version('WebKit','3.0')
#Import the modules that will give us a Graphical User Interface (GUI) and a WebKit Browser.
from gi.repository import Gtk,WebKit
#Define your function to handle the WebKit's "load-finished" event. The webobj is a reference to the WebKit that triggered the event. The frame is which frame triggered the event (useful if the loaded page has multiple frames like a frameset.
def ShowSource(webobj,frame):
#What you have printed is what results from this line. This line returns a reference to an object, so when you print it's return value, a description is all Python knows to print.
SourceCodeStringObject=frame.get_data_source().get_data()
#You can get the text the object is carrying from it's "str" member property like I do below.
SourceCodeStringText=SourceCodeStringObject.str
#Send the source code string text to the output stream.
print(SourceCodeStringText)
#Create Window object.
Window=Gtk.Window()
#Set the text to display in the window's caption.
Window.set_title("Test of Python GTK and WebKit")
#Set the starting window size in pixels.
Window.set_default_size(480,320)
#Create the WebView object.
WebBrowser=WebKit.WebView()
#Tell the WebView object to load a website.
WebBrowser.open("https://stackoverflow.com/questions/24119290/pygtk-webkit-get-source-html")
#Set the event handler for the WebView's "load-finished" event to the function we have above.
WebBrowser.connect("load-finished",ShowSource)
#Add the WebView to the window.
Window.add(WebBrowser)
#Set the handler of the window closing to cause GTK to exit. Without this, GTK will hang when it quits, because it's main loop that we start later will still be running. Gtk.main_quit will stop the main loop for GTK.
Window.connect("delete-event",Gtk.main_quit)
#Display the window.
Window.show_all()
#Start GTK's main loop.
Gtk.main()
This way works for me.
#!/usr/bin/env python
import webkit, gtk
def get_source(webobj, frame):
print "loading..."
x = web.get_main_frame().get_data_source().get_data()
print x
win = gtk.Window()
win.set_position(gtk.WIN_POS_CENTER_ALWAYS)
win.resize(1024,768)
win.connect('destroy', lambda w: gtk.main_quit())
win.set_title('Titulo')
vbox = gtk.VBox(spacing=5)
vbox.set_border_width(5)
web = webkit.WebView()
vbox.pack_start(web, fill=True, expand=True)
web = webkit.WebView()
web.open("http://www.google.co.ve")
web.connect("load-finished", get_source)
browser_settings = web.get_settings()
browser_settings.set_property('user-agent', 'Mozilla/5.0 (X11; Linux i586; rv:31.0) Gecko/20100101 Firefox/31.0')
browser_settings.set_property('enable-default-context-menu', True)
browser_settings.set_property('enable-accelerated-compositing', True)
browser_settings.set_property('enable-file-access-from-file-uris', True)
web.set_settings(browser_settings)
win.add(web)
win.show_all()
gtk.main()

Qt: Take over system open file dialog

I would like to automate the upload of a file to a website using PyQt4's QWebView, but there's a part I can't figure out yet. To upload the file, the website has a button, which opens a dialog from which you are supposed to select the local file. So, these are my questions :) Is there a way to control that dialog once I click the button? Is there a better way to achieve this?
edit
The website is https://maps.google.com/ and I'm uploading a .kml file through My Places > Create Map > Import.
It is possible what you're looking for is QWebPage::chooseFile() (I suppose it depends also on how the website is handling that). Reimplement that and see if it is sufficient. Do whatever you want and return the chosen file path.
EDIT: Now that you provided the link I tested and seems to work.
Ok, to begin let me start with background information and references.
The module that I will be using is pywin32 download here, specifically the win32gui, API reference here.
Now before you can manipulate the dialog you have to "navigate" to the window handle, the following uses win32.FindWindow API Reference here, which looks like this, where the two inputs are the lpclassName in this case #32770 (stands for a dialog) reference here and the lpWindowName which in this case is File Upload,
HWND WINAPI FindWindow(
_In_opt_ LPCTSTR lpClassName,
_In_opt_ LPCTSTR lpWindowName
);
Code to locate file handle:
import win32gui
control = win32gui.FindWindow("#32770", "File Upload")
And it stores the handle, which in my case was 721470.
The next step is locate the handles of the GUI objects in the dialog, i will show an example of the Cancel button. To find the handle, I wil be using FindWindowEx API reference here,
import win32con
import win32api
ButtonHandle = win32gui.FindWindowEx(control, 0, "Button", "Cancel");
win32api.SendMessage(ButtonHandle, win32con.BM_CLICK, 0, 0)
Reference here for the BM_CLICK and here for the SendMessage.
Final code:
import win32gui
import win32api
import win32con
window = win32gui.GetForegroundWindow()
title = win32gui.GetWindowText(window)
control = win32gui.FindWindow("#32770", "File Upload")
ButtonHandle = win32gui.FindWindowEx(control, 0, "Button", "Cancel")
win32api.SendMessage(ButtonHandle, win32con.BM_CLICK, 0, 0)
Another way is to use the watsup.winGuiAuto module, here, example below:
from watsup.winGuiAuto import *
optDialog = findTopWindow(wantedText="File Upload")
CancelButton = findControl(optDialog,wantedClass="Button", wantedText="Cancel")
clickButton(SaveButton)
But i believe the easiest way is to use autoit here, i have used it before in pyqt, to shoot out commands.
Hope this helps!
Additional References (pywin32 versions):
win32gui here
win32api here
Here's a pure PyQt4 demo that more or less reproduces the default implementation:
import sys
from PyQt4 import QtCore, QtGui, QtWebKit
class WebPage(QtWebKit.QWebPage):
def chooseFile(self, frame=None, path=''):
return QtGui.QFileDialog.getOpenFileName(self.parent(), '', path)
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
view = QtWebKit.QWebView()
view.setPage(WebPage(view))
view.load(QtCore.QUrl('https://maps.google.com/'))
view.show()
sys.exit(app.exec_())

How to Acces Button In TDBNavigator (exe build with Delphi) using pyWinAuto

How to Acces Button In TDBNavigator using pyWinAuto ?
when id call method print_control_identifiers i can not find buttons in DBNavigator.
here is my Code :
import time
try:
from pywinauto import application
except ImportError:
import os.path
pywinauto_path = os.path.abspath(__file__)
pywinauto_path = os.path.split(os.path.split(pywinauto_path)[0])[0]
import sys
sys.path.append(pywinauto_path)
from pywinauto import application
from pywinauto import tests
from pywinauto.findbestmatch import MatchError
from pywinauto import findwindows
from pywinauto import WindowAmbiguousError
from pywinauto.controls import WrapHandle
from pywinauto.timings import Timings
Timings.Fast()
app = application.Application()
app.connect_(path = "D:\SharedProjects\Projects\pyWinAuto\PYWINAUTO.exe")
pwin = app.MAIN
pwin.MenuSelect("Transaksi->Form 2")
frmDua = app['Form Dua']
frmDua.print_control_identifiers()
dbNavigator = frmDua['TDBNavigator']
dbNavigator.print_control_identifiers()
result of dbNavigator.print_control_identifiers() are :
Control Identifiers:
TDBNavigator - '' (L673, T285, R1335, B310)
'3' 'TDBNavigator'
there is not button in TDBNavigator. So, how can i access btnFirst, btnPrev, btnInsert, etc
Yes , Finaly I Found It
dbNavigator = frmDua['TDBNavigator']
dbNavigator.SetFocus()
SendKeys.SendKeys("""{LEFT 10}""") #Move Cursor To Most LeftButton
SendKeys.SendKeys("""{RIGHT 4}""") #Move Cursor To InsertButton
SendKeys.SendKeys("""{SPACE}""") #Perform Click On Insert Button

Get text from popup window

I'm trying to read the text from a popup window.
The title is always the same. I've managed to identify the hwnd and get the title with the code below, but I can't figure out how to read the contents.
import time
import win32gui, win32con
windows = []
def _MyCallback( hwnd, extra ):
extra.append(hwnd)
win32gui.EnumWindows(_MyCallback, windows)
while True:
window = win32gui.GetForegroundWindow()
title = win32gui.GetWindowText(window)
if title == 'Errors occurred': print 'error window'
time.sleep(1)
Here's the working version:
import time
import win32gui
while True:
window = win32gui.GetForegroundWindow()
title = win32gui.GetWindowText(window)
if title == 'Errors occurred':
control = win32gui.FindWindowEx(window, 0, "static", None)
print 'text: ', win32gui.GetWindowText(control)
time.sleep(1)
You will only be able to read this text programmatically if it is contained in a windowed control. You can easily check this with Spy++. Many GUI frameworks don't use windowed controls for their child controls, or only use windowed controls for some children.
If it is a windowed control then you can identify it by calling GetWindow() and walking the child structure (obviously you need to use the win32gui equivalent).
I don't have access to the framework or the error dialog you are using, so I can only say in general what you want.
You need the FindWindowEx function, and use it to find a control whose class name is 'static' (or whatever the class name of the control is). I imagine this would be the line:
control = win32gui.FindWindowEx(window, 0, "Static", 0)
That returns the handle to the control, and you can then use GetWindowText on that to get the text.

Categories

Resources