Windows-(GUI-)Programme mit Python fernsteuern

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

6 Gedanken zu “Windows-(GUI-)Programme mit Python fernsteuern

  1. 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 ;)

  2. 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 :)

Schreibe einen Kommentar

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s