Błąd przy automatycznym wypełanianiu pola Login i Hasło

0

Witam.
Chciałbym napisać swój kreator kont pocztowych, coś takiego jak ten wbudowany w MailShare, Moorhunta czy Ygoowa. Na początek wybrałem zakładanie kont na wp.pl. Napisałem kod w C# (w Visual Studio 2013), który nie do końca działa - ładuje się strona w programie, klikam "Nowe konto" i wszystkie pola się wypełniają. Problem w tym, że dwa pola "Login" i "Hasło" też są wypełnione, a świecą na czerwono, reszta ok.
user image
Lecz gdy np. skasuję jakiś znak (np. ostatni - "a" jak na screenie) i wpiszę go ponownie z klawiatury to zaczyna świecić na zielono. Z hasłem podobnie. Gdy na przykład dopiszę jakąś literę z klawiatury do obecnego hasła, to też działa. Zamieszczam poniżej fragment kodu, siedziałem nad tym kilka dobrych godzin, przeszukałem Google i nic... Fajnie, gdyby ktoś poradził / napisał co jest nie tak.

public Form1()
{
	InitializeComponent();
}

private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
	if (e.Url.AbsolutePath != (sender as WebBrowser).Url.AbsolutePath)
		return; 
}

private void Form1_Load(object sender, EventArgs e)
{
	webBrowser1.Navigate("https://profil.wp.pl/rejestracja.html");
}

private void button1_Click(object sender, EventArgs e)
{
	string url;
	HtmlElementCollection theElementCollection;
	theElementCollection = webBrowser1.Document.GetElementsByTagName("img");
	foreach (HtmlElement curElement in theElementCollection)
	{
		if (curElement.GetAttribute("src").ToString().Contains("https://si.wp.pl/captcha?"))
		{
			url = curElement.GetAttribute("src").ToString();
			pictureBox1.Load(url);
		}
	}
	webBrowser1.Document.GetElementById("firstName").SetAttribute("value", imie);
	webBrowser1.Document.GetElementById("lastName").SetAttribute("value", nazwisko);
	webBrowser1.Document.GetElementById("plec-mężczyzna").InvokeMember("click");
	webBrowser1.Document.GetElementById("birthDateDay").SetAttribute("value", dzien2);
	webBrowser1.Document.GetElementById("birthDateMonth").SetAttribute("value", miesiac2);
	webBrowser1.Document.GetElementById("birthDateYear").SetAttribute("value", rok2);
	webBrowser1.Document.GetElementById("login").SetAttribute("value", imie + nazwisko);
	webBrowser1.Document.GetElementById("darmowa").InvokeMember("click");
	webBrowser1.Document.GetElementById("cloudAccount").InvokeMember("click");
	webBrowser1.Document.GetElementById("password").SetAttribute("value", haslo);
	webBrowser1.Document.GetElementById("passwordRepeat").SetAttribute("value", haslo);            
	webBrowser1.Document.GetElementById("helperEmail").SetAttribute("value", email + "@wp.pl");
	webBrowser1.Document.GetElementById("citySize").SetAttribute("value", "1");
	webBrowser1.Document.GetElementById("education").SetAttribute("value", "1");
	webBrowser1.Document.GetElementById("job").SetAttribute("value", "1");
	webBrowser1.Document.GetElementById("zgodaTerms").InvokeMember("click");
}

private void button2_Click(object sender, EventArgs e)
{
	webBrowser1.Document.GetElementById("captchaCode").SetAttribute("value", textBox1.Text);
	webBrowser1.Document.GetElementById("btnSubmit").InvokeMember("click");
	richTextBox1.AppendText("L: " + imie + nazwisko + "@wp.pl" + "\n");
	richTextBox1.AppendText("P: " + haslo +"\n");
	richTextBox1.AppendText("\n");
}
 
0

Spróbuj zrobić 'fire event' na wszystkich walidowanych (login, password) polach, wtedy uruchomią się listenery i pewnie się zaświeci na zielono. Ten InvokeMember na click powinien dać radę.

0

Próbowałem zrobić tak:

webBrowser1.Document.GetElementById("login").SetAttribute("value", znaklos3 + znaklos2 + znaklos1 + znaklos3);
webBrowser1.Document.GetElementById("login").InvokeMember("click");

zero zmian.

Próbowałem zrobić tak:

webBrowser1.Document.GetElementById("login").SetAttribute("value", znaklos3 + znaklos2 + znaklos1 + znaklos3);
SendKeys.Send("{TAB}");

i wtedy pole także świeci na czerwono.

Próbowałem zrobić także tak:

        void pwd_GotFocus(object sender, HtmlElementEventArgs e)
        {
            HtmlElement pwd = (HtmlElement)sender;
            pwd.SetAttribute("value", "2");
        }
///////////////////////////
            HtmlElementCollection inputs = webBrowser1.Document.GetElementsByTagName("input");
            HtmlElement pwd = inputs.GetElementsByName("login")[0];
            pwd.GotFocus += new HtmlElementEventHandler(pwd_GotFocus);
            pwd.Focus();
webBrowser1.Document.GetElementById("login").SetAttribute("value", znaklos3 + znaklos2 + znaklos1 + znaklos3);
0

Przypadkiem wysłałem poprzedni post i nie mogę go zedytować, dopisuję dalszy ciąg:

I też to nie działa.
xeo545x39, dzięki za odpowiedź, chyba zrobiłem to, co napisałeś, nie? :)
Czekam na inne pomysły, już 3 dni nad tym siedzę, a pewnie na końcu okaże się, że brakuje jednej linijki...

0

A na jaki event odpala się da walidacja na stronie? Sprawdź event listenery w Chrome np. Może na onChange wtedy zamiast click trzeba na change. W sumie na click pola raczej taka walidacja nie ma sensu więc tu wtopa :P

0

user image
Spróbowałem z "change" i "onchange". Nie zadziałało.

Ale naprowadziłeś mnie na dobry trop i znalazłem coś takiego:
http://stackoverflow.com/questions/9604722/webbrowser-and-javascript

wydaje mi się, że właśnie w tym tkwi problem,

that the DocumentCompleted event is being fired before the javascript
tylko nie wiem, jak się za to zabrać / jaki kod JavaScript umieścić w programie (i w którym miejscu), aby to zadziałało...

0

Wszedłem na tą stronę i jQuery zrobiłem .change() na loginie i haśle - zadziałało (Chrome). W kodzie C# na pewno nie działa InvokeMember na change?

0

Sprawdzałem właśnie różne kombinacje, m.in.:

webBrowser1.Document.GetElementById("login").SetAttribute("value", znaklos3 + znaklos2 + znaklos1 + znaklos3);
webBrowser1.Document.GetElementById("login").InvokeMember("change");
webBrowser1.Document.GetElementById("login").SetAttribute("value", znaklos3 + znaklos2 + znaklos1 + znaklos3);
webBrowser1.Document.GetElementById("login").RaiseEvent("change");
webBrowser1.Document.GetElementById("login").SetAttribute("value", znaklos3 + znaklos2 + znaklos1 + znaklos3);
webBrowser1.Document.GetElementById("login").InvokeMember("onchange");

Na pewno nie działa.

0

Spróbuj keyup. U mnie na IE zadziałało. Na tym evencie też jest walidacja.

0
webBrowser1.Document.GetElementById("login").SetAttribute("value", znaklos3 + znaklos2 + znaklos1 + znaklos3);
webBrowser1.Document.GetElementById("login").InvokeMember("keyup");

Niestety nic...

Może jest jakiś błąd w kodzie i rzeczywiście

DocumentCompleted event is being fired before the javascript
??

    public Form1()
    {
        InitializeComponent();
        webBrowser1.ScriptErrorsSuppressed = true;
    }

    private void konto_wp()
    {
        //random variables
        webBrowser1.Document.GetElementById("firstName").SetAttribute("value", imie);
        webBrowser1.Document.GetElementById("lastName").SetAttribute("value", nazwisko);
        webBrowser1.Document.GetElementById("plec-mężczyzna").InvokeMember("click");
        webBrowser1.Document.GetElementById("birthDateDay").SetAttribute("value", dzien2);
        webBrowser1.Document.GetElementById("birthDateMonth").SetAttribute("value", miesiac2);
        webBrowser1.Document.GetElementById("birthDateYear").SetAttribute("value", rok2);
        webBrowser1.Document.GetElementById("login").SetAttribute("value", znaklos3 + znaklos2 + znaklos1 + znaklos3);
        webBrowser1.Document.GetElementById("darmowa").InvokeMember("click");
        webBrowser1.Document.GetElementById("cloudAccount").SetAttribute("checked", null);
        webBrowser1.Document.GetElementById("password").SetAttribute("value", znaklos4 + znaklos2 + znaklos3 + znaklos1);
        webBrowser1.Document.GetElementById("passwordRepeat").SetAttribute("value", znaklos4 + znaklos2 + znaklos3 + znaklos1);
        webBrowser1.Document.GetElementById("helperEmail").SetAttribute("value", email + "@wp.pl");
        webBrowser1.Document.GetElementById("citySize").SetAttribute("value", miejscowosc2);
        webBrowser1.Document.GetElementById("education").SetAttribute("value", wyksztalcenie2);
        webBrowser1.Document.GetElementById("job").SetAttribute("value", zawod2);
        webBrowser1.Document.GetElementById("zgodaTerms").SetAttribute("checked", "true");
        webBrowser1.Document.Body.ScrollIntoView(false);
    }

    private void button1_Click(object sender, EventArgs e)
    {
        //random variables
        webBrowser1.Navigate(@"https://profil.wp.pl/rejestracja.html");
        while (webBrowser1.ReadyState != WebBrowserReadyState.Complete)
        {
            Application.DoEvents();
            System.Threading.Thread.Sleep(1);
        }
        konto_wp();
    }

    private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
    {
        var webBrowser1 = sender as WebBrowser;
        webBrowser1.DocumentCompleted += webBrowser1_DocumentCompleted;
    }

Sprawdziłem na innym komputerze, bo myślałem, że to problem z IE. Tam też nie działa.

0

A to podpięcie eventu w handlerze to po co? Z każdym completed wywoła się co raz więcej jeszcze tego samego. Sprawdziłem tak jak pisałem eventy na keyup i odpaliła się walidacja pola, jeżeli z kodu invoke nie działa na keyup to już nie mam na razie pomysłów.

Ewentualnie skoro tak nie działa to załadować dynamicznie do dokumentu na sam koniec po loadzie kawałek JS tudzież funkcję, która odpala keyup w jQuery po stronie klienta. Zostaje ją wykonać tam gdzie ma być odpalana walidacja.

0

Tylko nie wiem, jak załadować tą funkcję i w którym miejscu. Ale to może się udać, bo mi cały czas się wydaje, że problem jest z eventem DocumentCompleted i takie wywołanie funkcji "na siłę" powinno załatwić sprawę :)

A i jeszcze raz dzięki, że chce ci się wymyślać nowe rozwiązania i odpowiadać. Jako jedyna osoba na całe forum.

0

Tu jest np. jak wstrzyknąć kod skryptu do html http://codereview.stackexchange.com/questions/60426/manipulate-html-document-loaded-into-webbrowser-control
A z tym eventem to co masz konkretnie na myśli, że jest problem? Pisałeś, że się wykonuje przed JS, ale to nie wadzi, bo w sumie nie widzę byś gdziekolwiek (a podałeś 2 wersje handlera eventu) coś robił w tym handlerze.

0

Jak napisać tą funkcję, która odpala keyup czy inną walidującą pole login? Na stronie jest taki kod:

.keyup(function(){

			clearTimeout(loginAvailableTimeout);

			loginAvailableTimeout = setTimeout(function(){
				if (isLogin(login)) {

					login.info.hide();
					login.addClass("loading");

					$.getJSON(ACTION_LOGIN_AVAILABLE, {

						login: cleanValue(login),
						name: firstName.val(),
						surname: lastName.val(),
						year: birthDateYear.val()

					},function(response){

						login.removeClass("loading");

						//Utils.log(response);
						loginSuggestionsItems.empty();
						emailAccountType.info.hide();

						if (response.available)
						{
							isLoginAvailable = true;
							if (withEmailAccount)
							{
								//helperEmail.val(cleanValue(login) + "@wp.pl").change();
								loginSuggestionsInfo.html("Login <strong>"+cleanValue(login) + "</strong> jest dost\u0119pny.");
								loginSuggestionsItems.hide();
								loginSuggestions.fadeIn();
								login.change();
							}
						}
						else
						{
							isLoginAvailable = false;
							if (response.suggestions.length)
							{
								var item;
								loginSuggestionsInfo.html("Login <strong>"+cleanValue(login) + "</strong> jest zaj\u0119ty, mo\u017ce wybierzesz?");

								for (var i in response.suggestions) {
									item = $("<li>").text(response.suggestions[i]).bind("click", onSuggestionClick)
									loginSuggestionsItems.append(item);
								}
								loginSuggestionsItems.show();
								loginSuggestions.fadeIn();
								login.nextAll(".deco").removeClass("success");
							}
						}
					});
				} else if (!isEmpty(login)) {
					login.change();
				}
			}, 500);
		}

Próbuje i próbuje i żadna moja kombinacja nie działa. Widziałem też zmienną

isLoginAvailable
Może gdyby jakoś ustawić ją na true, to też zadziała? Tylko jak to zrobić..

1

Chodziło mi o odpalenie eventu w jQuery opakowane w funkcję by wywołać z kodu C#:

function custom_fireValidation() {
    $("#login").keyup(); // wypada jeszcze sprawdzić dokładnie na jaką kontrolkę jest przypięty event, żeby się nie okazało, że event jest na coś "pod tym", jakiś div cokolwiek (już nie pamiętam jak było na stronie)
}

Teraz wstrzyknąć taki oto skrypt dynamicznie do HTMLDocument i wywołać tą funkcję custom_fireValidation();.

Powinien się odpalić ten kod który wkleiłeś, on Cię już nie obchodzi (np. isLoginAvailable - nie możesz sztucznie sobie stwierdzić czy jest czy nie, bo potem np. serwer odrzuci), powinien zrobić swoje czyli zwalidować pole i pozwolić iść dalej.

0

xeo545x39, jesteś mistrzem!! :)

Znalazłem w Internecie, jak zrobić to, co napisałeś:

webBrowser1.Document.GetElementById("login").SetAttribute("value", znaklos3 + znaklos2 + znaklos1 + znaklos3);
string jCode = "$('#login').keyup();";
webBrowser1.Document.InvokeScript("eval", new object[] { jCode });

i to działa. W końcu!

Mam jeszcze jedną prośbę - to samo, tylko, że z polem hasło... Bo spróbowałem z keyup i change i blur:

webBrowser1.Document.GetElementById("password").SetAttribute("value", znaklos4 + znaklos2 + znaklos3 + znaklos1);
string jCode2 = "$('#password').keyup();";
webBrowser1.Document.InvokeScript("eval", new object[] { jCode2 });

i niestety znowu hasło świeci na czerwono...

0

Możesz sprawdzić na oryginalnej stronie jakie eventy się wykonują: http://stackoverflow.com/questions/10213703/how-do-i-view-events-fired-on-an-element-in-chrome-web-developer
na tej kontrolce passworda i tak jak wspomniałem - login akurat może być zwykłą kontrolką, a password z racji tego, że jest to specyficzny textbox to coś pod nim łapie ten event a nie sam #password.

0

Sprawdziłem te eventy:
user image

Różnią się od loginu tym, że np. w keyup -> handler jest funkcja calculatePasswordPower:

function calculatePasswordPower(e) {

	Utils.info("calculatePasswordPower", e.type);

	//if (!passwordPowerInfo.is(":visible")){
	password.info.hide();
	passwordRepeat.info.hide();
	passwordPowerInfo.fadeIn();
	//}

	if (e && e.type == "keyup" && isKeyPrintable(e.which)) {

		validatePart(isPasswordLength, password, 0, updatePasswordPowerBar);
		validatePart(isPasswordComplicated, password, 1, updatePasswordPowerBar);
		validatePart(hasNoLogin, password, 2, updatePasswordPowerBar);

		clearTimeout(passwordRareTimeout);

		if (isPassword(password)) {

			isLoading = true;
			passwordRareTimeout = setTimeout(function() {
				$.getJSON(ACTION_PASSWORD_POPULAR, {
					password: cleanValue(password)
				}, function(response) {
					isLoading = false;
					validatePart(function() {
						return response.rare;
					}, password, 3, updatePasswordPowerBar);

					password.change();
					//if (!isPasswordComplete())
					//	password.focus();
				});
			}, 500);
		} else {
			clearTimeout(passwordRareTimeout);
		}
	}
}

password
		.keyup(calculatePasswordPower)
		.focus(function(e) {
	setTimeout(function() {
		calculatePasswordPower(e);
	}, 10);
});

Gdy wpisuję poprawne hasło, to zmieniają się:

class="row success"				
class="txt haslo success"
class="deco success"

Chyba nie znalazłem tego, co łapie event pod password. Albo źle szukam...

1

No jeżeli tak to łapie ten input, czyli tak jak w przypadku loginu.

Spojrzałem jeszcze raz w kod strony - zobacz jak wygląda handler na keyup - jest to calculatePasswordPower. Spójrz jaki jest jej kod i jaki jest zaraz na początku if i warunki. Podpowiem, że jeżeli robisz keyup samo to ostatnia funkcja w warunkach zwraca false, dlatego kod nie idzie dalej, bo nie ma e.which w parametrze eventu. Poczytaj i pomyśl jak wywołać event z parametrami dodatkowymi, żeby sztucznie wywołać keyup na faktycznie jakiś klawisz a nie w powietrze. Myślę, że to powinno pomóc.

0

Pomogło. Tak, jak napisałeś wywołałem keyup na klawisz "strzałka w lewo". Działa. No i jeszcze raz dzięki :)

1 użytkowników online, w tym zalogowanych: 0, gości: 1