Windows-(GUI-)Programme mit Python fernsteuern
by sparrow242
Wo wir schon gerade bei Python und Fernsteuerungen waren:
Es gibt ja immer mal wieder Anbieter von Softwareprodukten denen kann man einfach keine Schnittstelle für kleines Geld abschwatzen. Noch Schwieriger wird es wenn man über diese Schnittstelle nicht nur lesen sondern auch schreiben will. Da bekommen ganz, ganz viele Hersteller Bauchschmerzen und fangen mit so komischen Geschichten an wie “keine Haftung” und “Garantieverlust”.
Hallo? Ich will eine Schnittstelle? Baut die gefälligst so robust, dass ich damit gar nichts kaputt machen kann…
Glücklicherweise haben die meisten Programme eh eine Schnittstelle, nämlich die über die der Benutzer mit ihr interagiert. Die müsste man nur vernünftig mit einem Programm benutzen können. Da kann sich der Anbieter wohl kaum mit “Haftungsausschluss” heraus reden.
Zumindest unter Windows habe ich da mit Python eine ziemlich gute Lösung gefunden: pywinauto!
Vergleichbares gibt es sicherlich auch für andere Betriebssysteme, ich brauchte es aber für eine Anwendung die unter Windows läuft. Die Benutzung ist unglaublich einfach und eingängig. Nach 10 Minuten Einarbeitung ist das ganze geflutscht.
Offensichtlich kommt pywinauto auch mit relativ exotischen Toolkits zurecht, zumindest bei der Anwendung für das ich das Programm brauchte hatte ich überhaupt kein Problem, und das ist irendwas verwegen altes.
Um das noch einmal zu erklären: wir reden hier davon einen Benutzer an einem System zu “simulieren” indem wir Programmen Tastendrücke, Mausklicks, etc. schicken. Und das auf eine einfache Weise.
Ein kleiner Beispielcode:
from pywinauto import application
app = application.Application() # Applikationskontext erzeugen
app.start_("notepad.exe") # Externes Programm starten
app.notepad.TypeKeys("Hallo Welt", with_spaces = True) # Etwas tippen
app.notepad.TypeKeys("{ENTER}Ich kann hier automatisch Ticken",
with_spaces = True) # Noch mehr tippen
bs = "{BACKSPACE}" * 4
app.notepad.TypeKeys(bs + "ppen") # Vertipper entfernen
app.notepad.MenuSelect("?->Info") # Info aus dem Menü aufrufen
app.infoubereditor.OK.Click() # Im Info-Dialog OK klicken
app.notepad.MenuSelect("Datei->Beenden") # Über das Menü notepad beenden
app.editor.Nein.Click() # Nein, wir möchten nicht speichern
Hat ein bisschen gedauert bis ich darauf gekommen bin, dass Spezialtasten in geschweifte Klammern geschrieben werden. {ENTER}, {BACKSPACE} aber auch {F1}, etc, verhalten sich wie erwartet.
Hab ich schon erwähnt, dass ich es mag wenn es flutscht?
– der Würschtlmann
Was das nicht alles gibt
Aber es wirkt jetzt schon ungemein praktisch. Vielleicht ergibt es sich ja mal, das wir hier auch so einen Anwendungsfall haben.
Kommt es mir nur so vor oder Codest du gerade viel mehr als ich auf Arbeit
?
Ich finde das auch super.
in weniger als 60 Minuten hatte ich eine Schnittstelle als Python-Modul fertig. Inklusive Fehlerbehandlung, Typprüfung, etc.
Funktioniert super
Die letzte Frage kann ich dir nicht beantworten, ich weiß ja nicht wie viel (und vor allem: was) du so auf der Arbeit treibst
Hi,
interessanter Beitrag! Allerdings sehe ich nicht so ganz den Vorteil gegenüber Win32com aus den Win32 Extensions. OK, ein Extra-Modul braucht man für beide, daher ist es vielleicht egal, welches man nun installiert:
import win32api
import win32com.client
shell = win32com.client.Dispatch("WScript.Shell")
shell.Run("Notepad")
win32api.Sleep(1500)
shell.AppActivate("Notepad")
win32api.Sleep(1500)
shell.SendKeys("Hallo Welt!{ENTER}")
shell.SendKeys("%{F4}")
shell.SendKeys("{ENTER}")
win32api.Sleep(1500)
shell.SendKeys("Hallo.txt{ENTER}")
Na gut, bei meiner Variante könnte man auch gleich VBScript benutzen, wenn man schon auf den Windows Script Host setzt:
' SendkeyBeispiel.vbs
Option Explicit
Dim objWScriptShell
Set objWScriptShell = CreateObject("WScript.Shell")
objWScriptShell.Run "notepad"
Wscript.Sleep 1500 ' Warte bis Notepad fertig ist
objWScriptShell.SendKeys "Hallo Welt!{ENTER}"
objWScriptShell.SendKeys "%{F4}"
objWScriptShell.SendKeys "{ENTER}"
Wscript.Sleep 1500
objWScriptShell.SendKeys "Hallo.txt{ENTER}"
WScript.Quit
Viele Grüße
Christian
Hallo Christian,
ich bin halt als erstes über pywinauto gestolpert, und das hat gemacht was es sollte. Gott sei Dank hat man ja noch ab und zu die Wahl.
Kann man mit dem win32com-Modul auch die Menüs bedienen und die verschiedenen Fenster unterscheiden?
Gruß
Sebastian
Hallo Sebastian,
mmhhmm also Menüs bedienen würde ich über die Shortcuts machen, z.B. Strg + s als:
shell.SendKeys("^s")
Ob man Fenster unterscheiden kann, weiß ich allerdings nicht. COM-Objekte gehen aber:
import win32com.client
ie = win32com.client.Dispatch("InternetExplorer.Application")
ie.Visible = 1
ie.Navigate("http://www.datenteiler.de")
ie.GoHome()
ie.quit()
Und man hat die Möglichkeit, die Maus zu positionieren:
http://kvance.livejournal.com/985732.html
Viele Grüße
Christian
Ich komme ja eigentlich aus der Linux-Ecke, daher bin ich auch ziemlich unbewandert was diese VBScript-Geschichte angeht.
Ich muss leider einige “Unterfenster” bedienen, nämlich unter anderem den (nicht Windows-Standard) Druckdialog des Programm. Selbst das war ziemlich einfach.
Ich kann dir also nicht sagen, welche Variante besser ist, aber ich danke dir dafür, dass du hier eine Alternative gezeigt hast