![]() |
TWebBrowser - zwei Formulare nacheinander ausfüllen
Hallo zusammen,
Ich möchte mich, mittels TWebBrowser, auf einer Seite einloggen, und, nachdem ich eingeloggt bin, auf der anschließend erscheinenden Seite eine Nummer eingeben. Bis nach dem einloggen klappt alles ganz prima, nur, wenn ich auf der Folgeseite das Feld für die Nummer ausfüllen will, knallt's. Kann mir bitte jemand verraten warum?
Delphi-Quellcode:
Viele Grüße
procedure TForm1.Button1Click(Sender: TObject);
var x: variant; begin // br ist meine TWebBrowser-Komponente - mit unveränderten Standardwerten br.Navigate ('https://secure.freedomscientific.com/DealerILM/default.asp'); while br.ReadyState <> READYSTATE_COMPLETE do Application.ProcessMessages; x := br.OleObject.document.forms.item('input'); x.Elements.item('username').value := 'bla'; x.Elements.item('password').value := 'bla'; x.Elements.item('agree').click; x.submit; while br.ReadyState <> READYSTATE_COMPLETE do Application.ProcessMessages; // bis hierhin läuft alles ganz prima, und die Seite zur Eingabe der Nummer wird auch angezeigt. x := br.OleObject.document.forms.item('input'); x.Elements.Item('serial').value := '24520'; // und genau diese Zuweisung verursacht den Fehler. end; Marco |
AW: TWebBrowser - zwei Formulare nacheinander ausfüllen
Welcher Fehler??
![]() Ich rate jetzt einfach mal - du bekommst eine Zugriffsverletzung, oder? Wann immer du mit der Funktion Items() ein Objekt holst muss du prüfen ob es überhaupt existiert:
Delphi-Quellcode:
x := br.OleObject.document.forms.item('input');
if not Assigned(x) then raise Exception.CreateFmt('Web-Formalar %s nicht gefunden', ['input']); x.Elements.Item('serial').value := '24520'; |
AW: TWebBrowser - zwei Formulare nacheinander ausfüllen
Joa richtig, ;-), eine Zugriffsverletzung.
Der Tipp mit "assigned" ist schonmal gold wert, mir war nämlich nicht klar, auf was ich prüfen soll. Kann es sein, daß die Seite noch nicht fertig geladen ist? Oder anders gefragt: taugt die prüfung in der While-Schleife, oder gibt's 'ne bessere Methode um rauszufinden, wann er mit dem Seitenaufbau fertig ist? Vielen Dank schonmal und viele Grüße Marco p.s.:
Delphi-Quellcode:
findet mein Compiler überhaupt nicht witzig, da es "inkompatible Typen" sind - wohl weil's 'ne Variant ist...
if not assigned (x) then
|
AW: TWebBrowser - zwei Formulare nacheinander ausfüllen
Um darauf zu warten, dass eine Webseite komplett geladen ist würde ich folgenden Code verwenden:
Delphi-Quellcode:
Manchmal funktioniert das Submitten eines Webformulars nicht richtig; man kann das so umgehen:
procedure WaitForBrowser(WebBrowser:TWebBrowser);
begin while WebBrowser.ReadyState <> READYSTATE_COMPLETE do begin Application.ProcessMessages; Sleep(50); end; end;
Delphi-Quellcode:
Um zu prüfen, ob ein Variant ein Dispatch-Interface enthält:
procedure SubmitWebForm(webform:OleVariant);
var i : Integer; formitem : OleVariant; itemtype, itemname : string; begin // Schleife über alle Items eines WebFormulars For i:= webform.Length-1 downto 0 do begin formitem := webform.Item(i); itemtype := UpperCase(formitem.Type); itemname := UpperCase(formitem.Name); // if it's a submit button: click it if itemtype = 'SUBMIT' then begin formitem.Click; Exit; end else if (itemtype='BUTTON') and (itemname='SUBMIT') then begin formitem.Click; Exit; end end; // try default submit Method webform.submit; end;
Delphi-Quellcode:
Damit sieht der Test so aus:
function VarIsDispatchObject(const v : Variant): Boolean;
var vt : Integer; begin vt := VarType(v) and not varByRef; Result := (vt = varDispatch); end;
Delphi-Quellcode:
x := br.OleObject.document.forms.item('input');
if not VarIsDispatchObject(x) then raise Exception.CreateFmt('Web-Formalar %s nicht gefunden', ['input']); x.Elements.Item('serial').value := '24520'; |
AW: TWebBrowser - zwei Formulare nacheinander ausfüllen
Ich mache das mit dem Warten immer so:
Code:
repeat
Application.ProcessMessages; until ((Browser.ReadyState = READYSTATE_COMPLETE) and (Browser.Busy = False)); Auf alle Fälle würde ich kein Sleep nehmen. Hier wäre noch eine Variante:
Code:
procedure Delay(ATime: Integer);
var Start : Integer; begin Start := GetTickCount; repeat Application.ProcessMessages; until (GetTickCount - Start) > ATime; end; repeat Delay(100); until ((Browser.ReadyState = READYSTATE_COMPLETE) and (Browser.Busy = False)); |
AW: TWebBrowser - zwei Formulare nacheinander ausfüllen
Zitat:
Sleep gibt die Kontrolle an andere Prozesse ab, was ja genau das ist was während des Wartens auf den Internet Explorer gebraucht wird. Ohne Sleep würde die eigene Anwendung bis zu 100% Prozent (50% bei Dual-Core) an Rechenleistung unnötigerweise verbrauchen. Wer's nicht glaubt und selber testen möchte: * neues Projekt anlegen * neuen Button auf's Formular
Delphi-Quellcode:
Der Nachteil von sleep(50) ist, dass die Reaktionszeit auf Mausklicks, Tastendrücke um bis zu 50ms verzögert wird, aber diese Verzögerung ist so kurz, dass sie nicht zu spüren ist.
procedure TForm1.Button1Click(Sender: TObject);
begin while not Application.Terminated do Application.ProcessMessages; end; Des weiteren könnte der Webbrowser schon fertig geladen haben aber die eigene Anwendung bekommt dies erst nach 50ms mit. Auch das ist kein Beinbruch; im Gegenteil, wenn die Webseite komplett geladen ist sollte man dem Browser besser noch etwas Zeit geben eventuelle Java-Scripts abzuarbeiten. |
AW: TWebBrowser - zwei Formulare nacheinander ausfüllen
OK, ich hab es ausprobiert, überzeugt ;)
|
AW: TWebBrowser - zwei Formulare nacheinander ausfüllen
Hallo,
und erstmal vielen Dank für die raschen Antworten. Dank deines Codes Sx2008 bin ich dem Problem auf die Spur gekommen. Wenn ich nacheinander auf die Elemente des Forms zugreife, muß ich feststellen, daß es mein Feld "serial" gar nicht gibt, obwohl es angezeigt wird. Hä? Könnte das ein Cache-Problem oder so sein? Und wenn, wie kann man das Lösen? Sowas blödes, ich dachte,daß, was angezeigt wird ist auch daß, auf das ich via b.OleObject... zugreifen kann.... Viele Grüße Marco |
AW: TWebBrowser - zwei Formulare nacheinander ausfüllen
Es hilft doch sich den HTML-Code anzusehen ... oder?
|
AW: TWebBrowser - zwei Formulare nacheinander ausfüllen
Zitat:
Also dachte ich, bistde schlau, logstde dich ein und greifst, nachdem dein Programm auf "submit" gteklickt hat, eben auf dieses Feld zu. Aber genau das gibt's im Quelltext nicht, obwohls angezeigt wird, und mir ist nicht klar, wieso das so ist. Kann natürlich sein, daß die Seite, via Script oder sonstwie, die Formulare aufbaut, keine Ahnung, ich hab die Seite nicht programmiert. Vielleicht hat ja jemand 'ne idee? Viele Grüße Marco |
AW: TWebBrowser - zwei Formulare nacheinander ausfüllen
Liste der Anhänge anzeigen (Anzahl: 1)
Seltsam, wenn es angezeigt wird, dann muss es auch im Quelltext vorhanden sein ...
Im Anhang habe ich ein kleines Testprogramm mit einem TWebBrowser. Damit bis auf die Seite surfen und dann auf dem Analyzer-Tab auf "Untersuchen" klicken. Jetzt sollten dort alle Form-Elemente (INPUT, TEXTAREA, SELECT, BUTTON) aufgelistet werden, die es auf der aktuellen Seite gibt. Schau mal, ob das entsprechende Eingabefeld aufgelistet wird ... wenn es da ist, sollte es auch angezeigt werden. Die Quellen kann ich dir gerne zur Verfügung stellen, allerdings ist da auch einiges mit Generics drin, so dass dies mit Delphi 5 nicht läuft. |
AW: TWebBrowser - zwei Formulare nacheinander ausfüllen
Eine HTML-Seite kann mehr als ein Web-Formular enthalten.
Am Besten man lässt sich die Struktur in einem TreeView anzeigen.
Delphi-Quellcode:
function VariantIsObject(const value:OleVariant):boolean;
begin result := (VarType(value) = varDispatch); end; procedure Browser2TreeView(WebBrowser: TWebBrowser; root:TTreeNodes); var i,j, k :Integer; FormItem, Element, SubElement: OleVariant; child, child2, child3 : TTreeNode; s_type : string; begin Assert(Assigned(WebBrowser)); Assert(Assigned(root)); root.Clear; //count forms on document for I:=0 to WebBrowser.OleObject.Document.forms.Length -1 do begin FormItem := WebBrowser.OleObject.Document.forms.Item(I); if VariantIsObject(FormItem.Name) then child := root.AddChild(nil, 'Form'+IntToStr(i)+': '+FormItem.Name.Name) else child := root.AddChild(nil, 'Form'+IntToStr(i)+': '+FormItem.Name); child.ImageIndex := 3; For j:= 0 to FormItem.Length-1 do begin try Element := FormItem.Item(j); //when the fieldname is found, try to fill out child2 := root.AddChild(child, Element.Name+' = '+Element.Value); s_type := lowercase(Element.Type); if s_type = 'submit' then child2.ImageIndex := 1 else if s_type = 'text' then child2.ImageIndex := 0 else if s_type = 'file' then child2.ImageIndex := 2 else if s_type = 'hidden' then child2.ImageIndex := 4 else if s_type = 'checkbox' then child2.ImageIndex := 5 else if s_type = 'radio' then child2.ImageIndex := 6 else if s_type = 'select-one' then child2.ImageIndex := 7 else child2.ImageIndex := -1; child3 := root.AddChild(child2, 'Type='+s_type); child3.ImageIndex := -1; if s_type = 'text' then begin child3 := root.AddChild(child2, 'MaxLen='+IntToStr(Element.maxLength)); child3.ImageIndex := -1; end else if s_type = 'select-one' then begin for k := 0 to Element.Options.Length-1 do begin SubElement := Element.Options.Item(k); child3 := root.AddChild(child2, SubElement.Text+ ' = <'+SubElement.Value+'>'); child3.ImageIndex := -1; end; end; except on E:Exception do root.AddChild(child, E.Message); end; end; end; if root.Count > 0 then root.GetFirstNode.Expand(True); end; |
AW: TWebBrowser - zwei Formulare nacheinander ausfüllen
Hallo zusammen,
erstmal vielen Dank nochmal für die Hilfe! Super! Nach etwas gebastel mußte ich feststellen, es ist ein Zeitproblem. Warte ich nämlich nnicht, wie es ja sinnig ist, bis der Browser fertig ist, und lege dann los, sondern warte einfach 5 Sekunden, funktioniert alles prima. also
Delphi-Quellcode:
Irgendwie kriegt mein Programm nicht richtig mit, trotz br.ReadyStat, wann die Seite fertig ist. hä?
for i := 0 to 100 do
begin Application.ProcessMessages; Sleep (50); end; x := br.OleObject.document.forms.Item('input'); x.Elements.Item('serial').value := '24520'; Hat dazu noch jemand 'ne Idee, weil der Ansatz ist nicht nur dirty, sondern ganz dirty. ;-) Viele Grüße Marco |
AW: TWebBrowser - zwei Formulare nacheinander ausfüllen
Auf den WebBrowser wartet man wie folgt:
Delphi-Quellcode:
Allerdings hat man ein kleines Problem, wenn in der Website noch JavaScript enthalten ist, dass noch weitere Daten nachlädt.
procedure TMain_View.Browser_WebBrowserDocumentComplete( ASender : TObject; const pDisp : IDispatch;
const URL : OleVariant ); var CurBrowser, TopBrowser : IWebBrowser; begin CurBrowser := pDisp as IWebBrowser; TopBrowser := ( ASender as TWebBrowser ).DefaultInterface; if CurBrowser = TopBrowser then begin // Jetzt ist das Haupt-Dokument fertig geladen end; end; Auch frames (nicht iframes) werden in einem eigenen Kontext geladen. ALso muss man auch hier noch aufpassen. |
AW: TWebBrowser - zwei Formulare nacheinander ausfüllen
Hallo Zusammen,
Vielen Dank für eure Hilfe. Ich denke, diese Seite ist eine definitive Zumutung, denn die Formulare werden, wie auch immer, via Skript aufgebaut. Es gibt also keine wirklich Chance festzustellen, wann die Seite fertig geladen ist. Ich hab's jetzt schlicht so gemacht, daß ich 1. 3 Sekunden warte 2. warte, bis das gesuchte Formular vorhanden ist (varIsDispatchObject = true) und 3. warte, bis das Feld, das ich suche, da ist. So funktioniert's - ist nicht sehr schön aber tut, was es soll. Vielen Dank nochmal und viele Grüße Marco |
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:37 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz