Autor Beitrag
theend
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 56



BeitragVerfasst: Di 05.02.08 21:44 
Ich möchte folgendes umsetzen:

Ich habe ein Form auf dem ein WebBrowser Element eingebettet ist.

mit dem drücken eines Buttons soll ein BackgroundWorker gestartet werden.


Soweit so gut, nun will ich aber das in diesem BackgroundWorker auf das WebBrowser Element auf meinem Form zugegriffen werden kann also

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            CheckForIllegalCrossThreadCalls = false;
            
            webBrowser1.Document.Forms[0].GetElementsByTagName("Input").GetElementsByName("input1")[0].InnerText = "12345";

        }


allerdings bekomme ich Hier eine InvalidCastException

dies passiert auch wenn ich nur auf
ausblenden C#-Quelltext
1:
webBrowser1.Document					

zugreiffen will.

Das Dokument ist aber voll geladen.


Wie kann ich nun in diesem BackgroundWorker auf mein Webbrowser Element zugreiffen?
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Mi 06.02.08 09:43 
ausblenden C#-Quelltext
1:
CheckForIllegalCrossThreadCalls = false;					

Hältst du das für weise :shock: ? Soo aufwendig ist Synchronisierung mit dem Mainthread nun auch wieder nicht. Und wenn es nur um das Arbeiten mit dem Webbrowser geht, wird dir ein zweiter Thread rein gar nichts nützen.
theend Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 56



BeitragVerfasst: Mi 06.02.08 11:27 
user profile iconKhabarakh hat folgendes geschrieben:
ausblenden C#-Quelltext
1:
CheckForIllegalCrossThreadCalls = false;					

Hältst du das für weise :shock: ? Soo aufwendig ist Synchronisierung mit dem Mainthread nun auch wieder nicht. Und wenn es nur um das Arbeiten mit dem Webbrowser geht, wird dir ein zweiter Thread rein gar nichts nützen.


Hm.. ein Ja it kleiner hilfestellung oder ein klares NEIN wären mir als antwort eig. lieber gewesen.

ABER:

wieso wird mir hier ein zweiter Thread nichts nützen?

vl hast du ja eine bessere idee für mich folgendes umzusetzen:

1) ich lade eine seite
2) ich lade einen link auf dieser seite
3) ich fülle 1 feld aus und drücke einen Button der eine JScript funktion auslöst
4) browser ladet seite neu mit dem inhalt der JScript funktion das weitere felder befüllt
5) ich befülle 2 weitere felder
6) ich drücke auf submit
7) die seite wird neugeladen
8) ich checke auf einen string auf der Seite
9) ich gebe 1) Erfolgreich aus oder 2) ich ich übergebe die Fehlermeldung
10) ich lade neue parameter und starte das ganze von neuem.


zweck dieses tools ist ein automatisiertes testen gewisser funktionen einer Webseite ( meine eigene ).



Ein anderer Ansatz den ich versucht habe ist folgender:

ich starte aus dem BackgroundWorker Funktionen in meinem Form die für mich die arbeit im WebBrowser ereldigen sollen
zb.:
ausblenden C#-Quelltext
1:
2:
3:
4:
        private void setField(string arg1, string arg2, string arg3)
        {
            webBrowser1.Document.Forms[0].GetElementsByTagName(arg1).GetElementsByName(arg2)[0].InnerText = arg3;
        }


allerdings bekomme ich hier ebenfalls wieder einen InvalideCastException


Ich wäre über Hilfreiche Tips sehr erfreut!
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Mi 06.02.08 17:08 
du könntest versuchen, für jeden Thread einen eigenen Webbrowser zu benutzen, ich weiß aber nicht, ob sich das mit COM besser verträgt, Stichwort Single-Threaded Apartment.
Ansonsten nimmst du einzelne Prozesse, das funktioniert auf jeden Fall ;) . Viele wirst du ja nicht benötigen, da wohl eher die Netzwerkverbindung als die CPU der Flaschenhals ist (weshalb ich mir gut vorstellen kann, dass schon ein zweiter Thread nichts bessert).
theend Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 56



BeitragVerfasst: Mi 06.02.08 17:14 
mehere webbrwoser ist wegen einer userauth. nicht möglich, im hintergrund sind 1) loginadten gespeichert
2) wird von der webseite ein zweiter user parameter mitgegeben den ich benötige

somit fällt der einsatz von meherern webbrowsern flach.



das mit den einzelnen prozesen klingt interessant, hast du einen link wo ich mich einlesen kann bzw. mehr infos zubekommen kann?

danke


//Edit: Bleibt aber immer noch die Frage, ist es möglich auf das WebBrowser Element zuzugreifen aus einem anderen Thread? bzw. wieso kommt dabei eine InvalideCastException. hat darauf jemand eine antwort?
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Mi 06.02.08 21:03 
user profile icontheend hat folgendes geschrieben:
mehere webbrwoser ist wegen einer userauth. nicht möglich, im hintergrund sind 1) loginadten gespeichert
2) wird von der webseite ein zweiter user parameter mitgegeben den ich benötige
Jetzt verstehe ich überhaupt nicht mehr, was du eigentlich parallelisieren willst :gruebel: .

user profile icontheend hat folgendes geschrieben:
das mit den einzelnen prozesen klingt interessant, hast du einen link wo ich mich einlesen kann bzw. mehr infos zubekommen kann?
Naja, einfach die Exe n-mal starten (lassen) :zwinker: .

user profile icontheend hat folgendes geschrieben:
bzw. wieso kommt dabei eine InvalideCastException. hat darauf jemand eine antwort?
Weil WebBrowser wie 99% aller anderen Klassen nicht threadsafe ist, da musst du schon synchronisieren (=> Control.Invoke). Wenn du aber die ganze Zeit am Synchronisieren bist, geht der Sinn des Multithreadings natürlich flöten, wie ich schon am Anfang geschrieben habe.
theend Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 56



BeitragVerfasst: Mi 06.02.08 21:17 
hm ok, ich versuchs nochmal zu erklären was genau mein problem ist:

also ich bin dabei ein tool zu schreiben, welches meine webseite automatisch testen soll (damit ich das nicht immer händisch alles durchklicken muss)

das problem ist, das ich einige seiten habe in denen JScript (onklick) mehtoden ausgeführt werden, die felder automatisch befüllen (wodurch die seite neugeladen wird)

so, da nun aber der webbrowser erst zu laden beginnt wenn zb. mein button klick event Fertig ist (da diese im selben thread laufen) kann ich mit einmal klicken nicht mehere abläufe durchführen.

folgendes szenario:
1) ich trage die URL in eine textbox und klicke eine button, danach logge ich mich ein.
2) dan will ich nocheinmal einen button klicken und das tool soll aufgrund gewisser parameter die ich lade einen link auf der seite finden
3) diesen klicken und die neue seite laden
4) daten eintragen und einen button klicken der ein JScript (onclick event) auslöst und die seite wieder neugeladen wird mit den daten die ich eingetragen habe + die durch das JScript eingetragen werden
5) ich trage weitere daten ein und klicke einen Button (Submit)
6) seite wird weitergeleitet und ich frage die neu geladene seite auf einen error string ab


da es wie bereits gesagt das problem gibt wenn ich zb.:

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
        private void button1_Click(object sender, EventArgs e)
        {
            webBrowser1.Navigate(textBox1.Text);

            //und hier noch ein paar sachen
        }


jetzt wird das webBrowser1.Navigate(textBox1.Text); erst dan gestartet sobald ich aus der button1_Click draussen bin.

da hatte ich die idee das ich das über einen zweiten Thread lösen kann der folgendes bewirkt:

1) er gibt die benötigten parameter an den Webbrowser und wartet dann bis er Brwoser fertig ist und macht weiter

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            CheckForIllegalCrossThreadCalls = false;
            
            webBrowser1.Document.Forms[0].GetElementsByTagName("Input").GetElementsByName("feldname")[0].InnerText = "1234567";
            HtmlElement abc = webBrowser1.Document.All["JScript Button mit oncklick methode"];
            object obj = abc.DomElement;
            System.Reflection.MethodInfo mi = obj.GetType().GetMethod("click"); 
            
            while (webBrowser1.IsBusy) { /*wait till browser has loaded site*/}
            webBrowser1.Document.Forms[0].GetElementsByTagName("Input").GetElementsByName("feldname n")[0].InnerText = "abcde";
        }


somit habe ich mir erhofft, das ich eine eingabe machen kann, und dan warten kann bis der Webbrowser die seite geladen hat und weitere eingaben akzeptieren kann ohne das ich händisch weitere buttons usw klicken muss.

danke aufjenden fall schon mal fürs nachdenken und für deine antwort oben. Ich hoffe das erklärt jetzt verständlich was ich versuche!
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Do 07.02.08 00:03 
user profile icontheend hat folgendes geschrieben:
so, da nun aber der webbrowser erst zu laden beginnt wenn zb. mein button klick event Fertig ist (da diese im selben thread laufen) kann ich mit einmal klicken nicht mehere abläufe durchführen.
Das sollte doch auch mit einem Thread funktionieren, wenn du die entsprechenden Events des WebBrowsers benutzt. Beispiel:
  • Button-Click-Methode ruft nur Navigate auf und beendet sich => WebBrowser kann die Seite laden.
  • Im Navigated/DocumentCompleted-EventHandler kannst du dann auf die geladene Seite zugreifen.
theend Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 56



BeitragVerfasst: Do 07.02.08 00:42 
wäre es ein rein statische application die nur einmal das ausführt wäre es mäglich, ich habe aber ein XML im hintergrund was mit genau ansagt navigiere dort hin, dan da und dan klicke dort usw.

damit ist es leider nciht mehr mäglich genau in den events des browsers alles zu erledigen

hm... aber ich werd mal drüber schlafen, vl fällt mir ja was ein.

danke
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Do 07.02.08 10:45 
Das kann einfach nicht sein :zwinker: . Jeden Code, den du in eine einzelne Methode schreiben kannst, kannst du auch über Eventhandler verteilen, du musst nur zwischen diesen irgendeinen Status in Feldern der Klasse speichern, im schlimmsten Falle also im Eventhandler ein
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
switch (step) {
  case 0:
    [...];
    step++;
    break;
  case 1: ...
theend Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 56



BeitragVerfasst: Do 07.02.08 17:24 
Ich hab es jetzt so gemacht

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
        private void button5_Click(object sender, EventArgs e)
        {
            //navigate some where

            //wait till browser is ready again
            Application.DoEvents();
            while (webBrowser1.ReadyState != WebBrowserReadyState.Complete)
            {
                Application.DoEvents();
            }
            //Do something after browser is loaded again
        }


damit ladet er den browser in den bereich neu ohne die fuktion/event zu verlassen