Während ich nach einer möglichen Lösung für dieses suchte, stieß ich auf mehrere Lösungen auf SO und anders. Einige von ihnen verwendeten AutoIT
oder das Bearbeiten von Browserprofilen, damit die Datei direkt ohne Eingabeaufforderung gespeichert wurde.
Ich fand alle diese Lösung zu spezifisch, wie Sie das Problem für den Speichern unter Dialog durch Bearbeiten des Browserprofils beheben können, aber wenn Sie später mit einem anderen Fenster umgehen müssen, dann stecken Sie fest. Für die Verwendung AutoIT
ist Overkill, kollidiert dies direkt für die Tatsache, dass ich Python
, um diese Aufgabe zu tun wählen. (Ich meine Python
ist selbst so mächtig, abhängig von einem anderen Werkzeug ist streng kein NEIN für jeden Pythonist)
So nach einer langen Suche nach einer möglichen generischen Lösung für dieses Problem, das nicht nur dient jemand, der zu handhaben sucht alle nativen OS-Dialogfelder wie "Speichern unter", "Datei-Upload" usw. bei der Automatisierung einer Web-Anwendung mithilfe des Selen-Web-Treibers, aber auch bei allen, die nur mit Python
APIs interagieren möchten.
Diese Lösung verwendet Win32gui
, Module von Python
. Ich werde zuerst eine generische Methode erklären, um jedes gewünschte Fenster zu erhalten, dann einen kleinen Codezusatz, der dies auch während der Automatisierung einer Webanwendung mit Selenium Webdriver nutzbar macht.
generische Lösung ::
import win32gui
import re
import SendKeys
class WindowFinder:
"""Class to find and make focus on a particular Native OS dialog/Window """
def __init__ (self):
self._handle = None
def find_window(self, class_name, window_name = None):
"""Pass a window class name & window name directly if known to get the window """
self._handle = win32gui.FindWindow(class_name, window_name)
def _window_enum_callback(self, hwnd, wildcard):
'''Call back func which checks each open window and matches the name of window using reg ex'''
if re.match(wildcard, str(win32gui.GetWindowText(hwnd))) != None:
self._handle = hwnd
def find_window_wildcard(self, wildcard):
""" This function takes a string as input and calls EnumWindows to enumerate through all open windows """
self._handle = None
win32gui.EnumWindows(self._window_enum_callback, wildcard)
def set_foreground(self):
"""Get the focus on the desired open window"""
win32gui.SetForegroundWindow(self._handle)
win = WindowFinder()
win.find_window_wildcard(".*Save As.*")
win.set_foreground()
path = "D:\\File.txt" #Path of the file you want to Save
ent = "{ENTER}" #Enter key stroke.
SendKeys.SendKeys(path) #Use SendKeys to send path string to Save As dialog
SendKeys.SendKeys(ent) #Use SendKeys to send ENTER key stroke to Save As dialog
diesen Code verwenden Sie eine Zeichenfolge zur Verfügung stellen müssen, die den Namen des Fensters Sie erhalten möchten, die in diesem Fall ‚Speichern unter‘. In gleicher Weise können Sie einen beliebigen Namen angeben und das Fenster fokussieren. Sobald Sie den Fokus des gewünschten Fensters haben, können Sie das Modul SendKeys
verwenden, um Schlüsselstriche an das Fenster zu senden, das in diesem Fall den Dateipfad zum Speichern der Datei und ENTER
enthält.
Spezifisch für Selen WebDriver ::
Das oben angegebene Codesegment verwendet werden kann native OS Dialogfelder zu behandeln, die bei der Automatisierung über eine Web-Anwendung ausgelöst werden, unter Verwendung von Selenium Webdriver
mit der Zugabe von wenig Code . Das Problem, mit dem Sie bei der Verwendung dieses Codes konfrontiert werden, ist, dass Ihr Steuerelement, sobald es auf ein Web Element
klickt, das ein natives Betriebssystemdialogfenster auslöst, an diesem Punkt festsitzt und auf eine Aktion im nativen Betriebssystemdialog wartet Fenster. Also im Grunde steckst du an diesem Punkt fest.
Die Arbeit ist um ein neues thread
mit Python
threading
Modul zu erzeugen, und verwenden Sie es auf dem Web Element
klicken, um das native OS-Dialogfeld und Ihre Muttergewinde auslösen wird in der Regel bewegen auf das Fenster zu finden, den Code I zeigte über.
#Assume that at this point you are on the page where you need to click on a Web Element to trigger native OS window/dialog box
def _action_on_trigger_element(_element):
_element.click()
trigger_element = driver.find_element_by_id('ID of the Web Element which triggers the window')
th = threading.Thread(target = _action_on_trigger_element, args = [trigger_element]) #Thread is created here to call private func to click on Save button
th.start() #Thread starts execution here
time.sleep(1) #Simple Thread Synchronization handle this case.
#Call WindowFinder Class
win = WindowFinder()
win.find_window_wildcard(".*Save As.*")
win.set_foreground()
path = "D:\\File.txt" #Path of the file you want to Save
ent = "{ENTER}" #Enter key stroke.
SendKeys.SendKeys(path) #Use SendKeys to send path string to Save As dialog
SendKeys.SendKeys(ent) #Use SendKeys to send ENTER key stroke to Save As dialog
#At this point the native OS window is interacted with and closed after passing a key stroke ENTER.
# Go forward with what ever your Automation code is doing after this point
HINWEIS ::
Wenn bei der Automatisierung einer Web-Anwendung den obigen Code verwenden, prüfen Sie den Namen des Fensters Sie suchen möchten und geben das zu find_window_wildcard()
. Der Name von Windows ist Browser abhängig. Z.B. Ein Fenster, das ausgelöst wird, wenn Sie auf ein Element zum Hochladen einer Datei klicken, heißt "Datei hochladen" in Firefox
und Öffnen in Chrome
. Verwendet Python2.7
Ich hoffe, dass dies jemand helfen wird, der nach einer ähnlichen Lösung sucht, ob es in irgendeiner generischen Form oder in der Automatisierung einer Webanwendung verwendet wird.
EDIT:
Wenn Sie versuchen, Ihren Code über die Befehlszeilenargumente dann versuchen zu laufen, den Faden zu verwenden, um das Fenster zu finden Win32gui
verwenden und den ursprünglichen Programm-Thread verwenden, um auf dem Element zu klicken (das ist hier mit dem Thread geklickt). Der Grund, die urllib Bibliothek wird einen Fehler werfen, während eine neue Verbindung mit dem Gewinde zu schaffen.)
Referenzen ::
SO Question
SenKeys
Win32gui
Welche Art von Interaktion du versuchst es zu tun? –
@DavidHeffernan Ich habe eine Webanwendung mit triggert ein neues Speichern als Dialogfeld.Ich muss in dem Sinne interagieren, dass ich auf verschiedene Optionen im Dialog klicken muss und den Zielpfad und den Dateinamen zum Speichern eingeben muss. – abhi
Warum der Downvote – abhi