Hi und Hoi,
mich würde es mal Interessieren, wie man in C# einen (z.B.) Button auf einer Website "klicken" kann.
Anwendung: ein Programm das zB web.de öffnet, die daten eingibt und dann anmeldet...
Wie ist so etwas möglich?!
thx and bye
Ein Button-Klick auf einer Webseite ist nichts anderes Submit. D.h. es wird ein Http-Request an eine Url gesendet. Parameter wie Benutzername und Passwort werden per GET- oder POST-Methode übertragen. Wenn es GET ist, stehen die Parameter in der Addressleiste. Für POST benötigt man einen Http-Sniffer, um die Http-Header mitschneiden zu können.
Such hier im Board, das Thema gab es schon mal.
Gruss
Pulpapex
Ich will ja hier nicht den Moralapostel spielen, aber ein wenig besser hättest Du Dein Vorhaben schon tarnen können... 😁
Hallo stephanruhland,
wenn du das Programm wirklich "klicken" lassen will (und nicht die Klicks in HTTP-Requests umsetzen, wie Pulpapex vorgeschlagen hat), kannst du das WebBrowser-Control aus .NET 2.0 oder die IE-Com-Komponente benutzen.
herbivore
hm kann mir jetzt noch nichts wirklich darunter vorstellen...
ich versuche einfach ein größeres programm zu schreiben was als funktion eben zB www.web.de öffnet dort die textboxen mit den zugangsdaten (die über eine oberfläche eingegeben wurden) füllt und anmeldet oder eben bei falscher anmeldung > meldung ...
hm mit beiden vorschlägen kann ich leider nicht so viel anfangen auch google hat nicht wirklich weitergeholfen...
könntet ihr das näher beschreiben..
@BigMAv mich würde Interessieren an was fuer ein Vorhaben du denkst...
ja danke... das sieht schonmal gut aus..
WebBrowser webbowser = new WebBrowser();
webbowser.Url = "http://www.gmx.de";
HtmlDocument htmldoc = ((WebBrowser)objSender).Document;
htmldoc.All["gmx_id"].InnerText = "xxx@gmx.de";
htmldoc.All["gmx_pw"].InnerText = "xxx";
htmldoc.All["login"].InvokeMember("Click");
aber was mir noch unklar ist: was meinst du mit objSender... wo ist da ein zusammenhang... mit was? :p
naja und als (webbrowser.)url nimmt er irgendwie kein string an aber das werd ich ihm schon noch klar machen...
DANKE
PS: 1. ich öffne die seite
2. ich gebe daten ein
3. ich bestätige
4. ?? seite anzeigen etc... ??
Hallo stephanruhland,
objSender ist in dem Fall der erste Parameter des DocumentCompleted-Eventhandlers, in dem ich den Code ausführe, denn die Seite, die durch
webbowser.Url = "http://www.gmx.de";
aufgerufen wird, muss ja geladen sein, bevor man weiter machen kann. Deshalb steht diese Zeile z.B. auch im Konstruktor und der andere Code eben im DocumentCompleted-Handler.
Der Code ist für .NET 2.0 beta 1. Wenn beta 2 hast (was ja wohl der Fall ist), musst du schreiben:
webbowser.Url = new Uri ("http://www.gmx.de");
Wenn du das Invoke ausgeführt hast, bekommtst du wieder ein DocumentCompleted, sobald die Folgeseite geladen ist. Wenn man im DocumentCompleted-Handler eine Unterscheidung nach der gerade geladenen Url macht, kann man das ganze Spiel auch über mehrere Seiten hinweg treiben.
Die jeweils geladene Seite wird im automatisch im WebBrowser-Control angezeigt. Man kann also verfolgen, was passiert.
herbivore
ok habe es jetzt mal umgesetzt...
sieht gut aus...
Seite wird geöffnet... Daten werden eingegeben... aber kein Login wird gemacht
habs auf verschiedenen seiten probiert..
woran könnte das liegen? hab auch eigentlich die "id" angepasst (login etc..)
Hallo stephanruhland,
und du rufst
htmldoc.All ["login"].InvokeMember("Click");
auf, wobei du für "login" die Id des Login-Knopfs eingesetzt hast?
herbivore
hab eigentlich die richtige ID jeweils genommen...
scheint aber immernoch nicht zu gehen... noch ne idee?
Hallo,
erstmal nicht, aber poste mal - wenn es nicht zu lang ist - den kompletten Code deines DocumentCompleted-Handlers und den Teil des Konstruktors, der sich direkt auf das WebBrowser-Control bezieht.
herbivore
hab mal ein eigenes Projekt zum testen geschrieben... also net so genau anschaun 😜
HtmlDocument htmldoc;
private void button_Click(object sender, EventArgs e)
{
webBrowser.Url = new Uri (textBox1.Text.Trim());
}
private void webBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
htmldoc = ((WebBrowser)sender).Document;
}
private void button2_Click(object sender, EventArgs e)
{
htmldoc.All[textBoxNameID.Text.Trim()].InnerText = textBoxName.Text.Trim();
htmldoc.All[textBoxPWID.Text.Trim()].InnerText = textBoxPW.Text.Trim();
htmldoc.All["login"].InvokeMember("Click");
}
private void Form1_Load(object sender, EventArgs e)
{
textBox1.Text = "http://www..de"; //URL
textBoxNameID.Text = ""; //IDs
textBoxPWID.Text = "";
textBoxName.Text = ""; //Zugangsdaten
textBoxPW.Text = "";
}
naja er schreibt alles rein aber "klickt" den Button nicht....
Hallo stephanruhland,
ich kann an deinem Programm nichts feststellen, warum es nicht gehen solle (außer das der Login-Button doch vielleicht eine andere Id als "login" hat). Trotzdem habe ich noch mal ein vollständiges Programm geschrieben, mit dem bei mir der Login bei web.de klappt. Musst halt nur deinen Usernamen und dein Passwort einsetzen:
using System;
using System.Windows.Forms;
using System.Drawing;
public class MyWindow : Form
{
private WebBrowser wb;
public MyWindow ()
{
ClientSize = new Size (640, 480);
Control ctrlCurr;
ctrlCurr = wb = new WebBrowser ();
ctrlCurr.Dock = DockStyle.Fill;
((WebBrowser)ctrlCurr).DocumentCompleted += WebBrowserDocumentCompleted;
Controls.Add (ctrlCurr);
wb.Url = new Uri ("http://web.de/");
}
protected void WebBrowserDocumentCompleted (
object objSender, WebBrowserDocumentCompletedEventArgs wbdcea
)
{
Console.WriteLine ("DocumentCompleted: " + wbdcea.Url);
if (wbdcea.Url == new Uri ("http://web.de/")) {
HtmlDocument htmldoc;
htmldoc = wb.Document;
htmldoc.All["inpLoginUsername"].InnerText = "dein usernanme";
htmldoc.All["inpLoginPassword"].InnerText = "dein passwort";
htmldoc.All["rv_dologon"].InvokeMember("Click");
}
}
}
abstract class App
{
[STAThread]
public static void Main (string [] astrArg)
{
Application.Run (new MyWindow ());
}
}
HTH
herbivore
ja stimmt bei web.de geht es...
danke für deine mühe!
aber warum gehts bei gmx.de net hm hast noch ne idee?!
Tach auch,
habe diesen Thread mit großen Interesse gelesen.
Nun frage ich mich allerdings, ob das alles auch mit VS 2003 (. NET Framework 1.1)
funktioniert. Läßt sich dort auch eine 'Webbrowser Control' einbinden ?
RF
Fleisch ist mein Gemüse
Hallo Ratzefummel,
die WebBrowser-Klasse gibt es unter 1.1 nicht. Es gibt aber wohl eine IE-COM-Componente, die ich noch nicht benutzt habe, die aber sehr ähnlich wie die WebBrowser-Klasse funktioniert. Wenn dein Code aber "zukunftsträchtig" sein soll, würde ich ihn gleich für die WebBrowser-Klasse schreiben.
Hallo stephanruhland,
ich habe mal bei gmx geschaut. Es ist das, was ich schon mehrfach vermutet habe: Der Login-Button hat nicht die Id "login".
Ob mein Code schon damals quatsch war oder GMX den HTML-Code geändert hat, weiß ich nicht. Momentan hat der GMX-Login-Button gar keine Id. Du musst dir den Button also auf eine andere Art holen, z.B. mit foreach über HtmlDocument.GetElementsByTagName ("INPUT") und für jedes Element schauen, ob OuterHtml "login" enhält (z.B. mit IndexOf).
herbivore
Hi,
hab leider keine ahnung wie das mit HtmlDocument.GetElementsByTagName ("INPUT") geht kann bitte jemand n codeschnipsel posten???
Hallo neo42,
mit foreach über HtmlDocument.GetElementsByTagName ("INPUT") und für jedes Element schauen, ob OuterHtml "login" enhält (z.B. mit IndexOf).
die Beschreibung ist doch schon fast so gut wie Code. Sorry, aber wenn du dafür auch noch Code willst, kommt mir das vor, als wenn du alles vorgekaut haben willst.
herbivore
hast recht, war ne dumme frage
also wenn ich
HtmlElementCollection collection = htmldoc.GetElementsByTagName("INPUT");
for (int i=0; i < collection.Count; i++)
{
if (collection[i].OuterHtml.IndexOf("uid") != -1)
{
Console.WriteLine(collection[i].OuterHtml);
break;
}
}
ausführe krieg ich raus welches element in der collection ich klicken muss, aber wie mach ich das genau?
htmldoc.All["irgendeine id"].InvokeMember("Click");
geht ja nicht da der button ja keine id hat
Hallo neo42,
du willst doch auf das gefundene Element klicken, gell? Also auf
collection[i].InvokeMember("Click");
herbivore
Hallo,
ich arbeite gerade ein einem Programm, mit dem einige Daten in Textboxen, Checkboxen, Listboxen... eingegeben werden, dann in einer eigenen Struktur gespeichert werden und dann an ein Online-System übergeben werden, indem die Onlineformulare ausgefüllt werden.
Klar, Text kann ich mit htmldoc["<id>"].InnerText eingeben, und mit InvokeMember("Click"); einen Click auslösen. Nun will ich aber auch solche Dinge wie Radio- und Checkboxen ausfüllen.
Hier mal ein kleiner Auszug aus einer HTML-Datei, die hier zwei Radio-Buttons zeigt.
Entweder ist der Radiobutton O (also Ost), oder der Button W (West) markiert.
__
_<TD align="right" width="55%" class='svborder'>Rechtskreis _
Ost <input type="radio" name="chkbnostwest" value="O" tabindex=7>
West <input type="radio" name="chkbnostwest" value="W" tabindex=8>
</td>
Kann mir nun jemand einen Tipp geben, wie ich den jeweiligen Radiobutton auf markiert setze?
thx
Hi,
ja, das habe ich probiert.
Ich denke, du meinst das
SetAttribute("value", "<wert>");
Wenn ich jetzt den HTML-Code von oben nehme und folgendes versuche:
htmldoc.All["chkbnostwest"].SetAttribute("value", "W");
dann ist aber dennoch keine der Boxen ausgewählt.
ChatBot hatte ich vorher auch schon gelesen, danke trotzdem. Siehst du vielleicht einen Fehler bei mir?
Hallo unsigned int,
htmldoc.All["chkbnostwest"].SetAttribute("checked", "checked");
sollte gehen.
herbivore
Hi,
auch wenn es eine blöde Frage sein mag,
wie lege ich dann fest, welches der beiden checked ist?
Wenn ich mehrere Radiobuttons mit dem selben Namen habe, dann kann ich die ja nicht einzeln festlegen, indem ich ("checked", "checked") angebe!? Wie lege ich denn fest, dass z.B. der zweite Button (value=W) checked ist.
thx
unsigned int
Hallo unsigned int,
ich habe es nicht getestet, aber ich denke es müsste gehen, wenn du SetAttribute mit checked/checked für den RadioButtton setzt, den du ausgewählt haben willst. Jeder RadioButton ist ja ein HtmlElement, dessen Attribute man ändern kann.
herbivore
Hi,
sorry, wenn ich nerve 😉,
aber mir ist noch nicht so richtig klar, wie ich auf die einzelnen HTML-Elemente zugreifen kann, da sie ja den gleichen Namen haben. Bei Elementen mit verschiedenen Namen ist das ja kein Problem für mich, aber hier unterscheiden sie sich ja nur am Value
Hallo unsigned int,
wenn alle Stricke reissen kann man immer die HtmlDocument.All-Collection durchsuchen.
Wenn du den HTML-Code selber schreibst, kannst du den RB aber einfach unterschiedliche IDs geben ( name= vs. id= ).
herbivore
Hi herbivore,
vielen Dank für deine unermüdliche Hilfe 🙂
Auch wenn es nicht mehr ganz den alten Komfort aufweist (gehe nun alle Elemente mit selbem Namen durch und vergleiche die Eigenschaft 'value'), funktioniert es jetzt endlich - endlich kann ich weitermachen 🙂
👍
möche auch button drücken:
private void btnKlick_Click(object sender, EventArgs e)
{
wbMain.Url = new Uri("http://u6.ogame.org");
HtmlDocument htmldoc;
htmldoc = wbMain.Document;
htmldoc.All["login"].InnerText = txtNick.Text.ToString(); // Marker
htmldoc.All["pass"].InnerText = txtPW.Text.ToString();
//htmldoc.All["rv_dologon"].InvokeMember("Click");
}
Nun bringt er mir aber einen fehler auf der höhe beim Marker
Er sagt es Objektverweis ist auf keine objektvariable festgelegt.
Was hab ich falsch gemacht?
Hallo B1rd,
alles was du wissen musst, steht in [FAQ] NullReferenceException: Der Objektverweis wurde nicht auf eine Objektinstanz festgelegt.
Vermutlich gibt es einfach kein Html-Element mit der Id oder dem Namen "login".
herbivore
doch gibts
<span class="rahmen"><input tabindex="2" alt="Login" class="eingabe" name="login"></span>
<span class="rahmen"><input tabindex="3" maxlength="20" alt="Passwort" class="eingabe" name="pass" type="password"></span></nobr>
nun ich bin jetzt mal mit dem debugger durch...
habe gesehen, dass bei der übergabe
wbMain.Url = new Uri("http://u6.ogame.org");
danach das Feld wbMain.Url immer noch den wert Blank hat und so unten
htmldoc = wbMain.Document;
das htmldoc keine richtigen daten enthält..
aber warum macht es das nicht?
dachte ich bin ganz schlau und mach eine pause rein.
also:
wbMain.Url = new Uri("http://u6.ogame.org");
System.Threading.Thread.Sleep(1000);
HtmlDocument htmldoc;
htmldoc = wbMain.Document;
doch auch das hat nichts genützt... muss ich das irgenwie manuel aktualisieren?
EDIT: habe den Fehler gefunden... Muss ja testen ob ich die verbindung schon aufgebaut habe...
aber jetzt füllt es meine Daten nicht in die felder obwohl die Items stimmen...
Hallo B1rd,
du weiß aber schon, dass bei Ogame keine Bots erlaubt sind?
herbivore
das heisst du spielst auch ogame? 😉
nun ja das weiss ich 🙂
Ich weiss nicht ob du stellara kennst.
Damit kann man daten von der galaxie-ansicht in eine externe Datenbank einlesen.
Nun möchte ich, dass ich automatisch die gala weitergehe...
ich werde natürlich zuerst noch einen go fragen ob ich das machen darf.
also für diese anwendung muss ich jetzt das ganze noch in firefox umsetzen.
Das geht mit dem auch oder?
Habe was gelsen, dass dies nur mit ActivX - steuerelementen möglich ist...
stimmt das?
Gruss
Hallo,
ich hab so in etwar das gleiche Vor. Leider klappte es auch bei mir nicht.
Den Fehler habe ich jetzt schon so weit ein gekreist, dass ich mir sicher bin das meine ID nicht korrekt ist.
Ich habe aber die ID von der Webseite und ich bin mir recht sicher das ich sie richtig da heraus gefiltert habe.
Gibt es noch eine möglichkeit alle IDs der Seite anzeigen zu lassen?
Das würde echt weiter Helfen. Danke!!!
Hallo EvilToken,
wenn du die IDs einfach nur wissen willst, ist es am einfachsten, du guckst in den HTML-Quelltext.
Natürlich kann man auch relativ einfach ein Programm schreiben, dass rekursiv durch ein HtmlDokument durch alle HtmlElements geht und HtmlElement.Id ausgibt, sofern eine Id gesetzt ist.
herbivore
Vieleicht probiere ich das mal aus.
Jetzt habe ich aber noch ein anderes Problem:
Ich habe keinen richtigen Button zu klicken habe sondert einen Link auf einem Bilder das den Login einleitet.
Gibt es da eine möglichkeit auf das Bild zu klicken?
Gruß EvilToken
Hallo EvilToken,
HtmlElement.InvokeMember ("Click")
geht für Links genauso wie für Buttons.
herbivore
Oh so einfach... Schön.
Danke nochmal und respekt an das myCSharp Forum. Hier bekommt man wirklich Hilfe.
@herbivore: Hab gerade deinen Code zum automatischen Einloggen ausprobiert.
Wenn ich anstatt web.de gmx.net verwende(bin nun mal bei gmx) kommt der mir nur bis zur Abfrage des Usernamens.
Die Abfrage des Passworts wird nie erreicht.
Kann es sein, dass folgende Zeilen falsch sind?
HtmlDocument htmldoc = ((WebBrowser)objSender).Document;
htmldoc.All["gmx_id"].InnerText = "meineadresse@gmx.de";
htmldoc.All["gmx_pw"].InnerText = "meinpasswort";
htmldoc.All["login"].InvokeMember("Click");
Wie kann ich den richtigen Namen der Textboxen rausfinden?
Ist das "gmx_id" richtig?
Gruß & Danke
Michael
Hallo smichae,
Wie kann ich den richtigen Namen der Textboxen rausfinden?
einfach in den Html-Quellcode der Seite gucken.
Ist das "gmx_id" richtig?
nein, "username" und "password". Oder "id" und "p".
Der Button heißt "inpLoginSubmit".
herbivore
Danke, das funktioniert.
Hab nicht gedacht, dass sowas so leicht geht.
Gruß
Michael
Hallo zusammen,
die oben beschriebenen Methoden zum Login verstehe ich und funktionieren bei mir auch. Ich habe allerdings eine Webseite mit einem Login, bei dem sich nach dem Klick auf einen Button ein Browser-Login-Fenster öffnet. Ich habe keine Idee, wie ich dieses ausfüllen soll, da mir ein Feld für das Passwort fehlt. Das html-Gerüst der Form sieht so aus:
<FORM METHOD=POST action="./">
<P>
<INPUT TYPE="hidden" name="lbutton" VALUE="login">
<INPUT TYPE="submit" VALUE="Login">
</FORM>
Hat von Euch einer eine Idee?
Hallo 11.08.2006,
es ist die Frage, was hier ein "Browser-Login-Fenster" ist.
Wenn es das Fenster ist, was der Browser anzeigt, wenn eine HTTP-Authentifizierung erforderlich ist (Stichwort: .htaccess), dann kannst du die Userdaten vermutlich einfach in der URL der abzurufenden Seite angeben: http://username:passwort@www.irgendwas.de/
Wenn es ein Fenster ist das per Javascript erzeugt wird: keine Ahnung.
herbivore
Es geht um die Seite http://212.184.207.130/
Das Problem ist wohl, dass der Login eine Email-Adresse ist und es dadurch Probleme mit dem @Zeichen gibt.
Hallo 11.08.2006,
so wie ich das sehe, ist das ein HTTP-Authentifizierung. Verwende statt dem @ in der E-Mail-Adresse %40.
herbivore