Dostanie się do zmiennej JavaScript w WebBrowserze

0

Witam. W WebBrowser ładuję stronę, która zawiera taki kod JavaScript:

<script type="text/javascript">
var zmienna = 0;
</script>

Jak w programie wczytać wartość tej zmiennej??

0

popatrz co siedzi w WebBrowser.Document, cos sensownego powinienes z tej wlasciwosci wyciagnac

0

Już zanim tu napisałem to przepatrzyłem... i nic nie znalazłem... :( Jakieś pomysły?

0
using System.IO;
using System.Text.RegularExpressions;

        {
            StreamReader sr = new StreamReader(webBrowser1.DocumentStream);
            Match m = Regex.Match(sr.ReadToEnd(), @"zmienna = (\d+);");
            MessageBox.Show(m.Success ? m.Groups[1].Value : "Nie znaleziono");
        }
1

Nie chciałbym siać defetyzmu, ale...

<html>
	<head></head>
	<body>
	<ul>OCENY:
		<li>Łukasz asd = 4;</li>
		<li>Zofia bla = 3;</li>
		<li>Ania zmienna = 4;</li>
	</ul>
	</body>
</html>

;-P

0

tak, ale zakładam że nie dojdzie do takiej sytuacji i to rozwiązanie wystarczy
jeżeli jednak nie i potrzebujesz czegoś mocniejszego, lub wartości zmiennej "zmienna" po policzeniu jej przez skrypt, lub wartość zmiennej która to w ogóle pojawia się w skrypcie dopiero po jakimś czasie, to oto przykładowy kod:

using System.Runtime.InteropServices;
using mshtml; // dodaj do references "Microsoft.mshtml" z zakładki .NET
		// lub Microsoft.HTML Object Libraty z zakładki COM
		// lub System32\mshtml.tlb z zakładki "Browse" jeżeli tamte nie istnieją

namespace WindowsFormsApplication1
{
    [ComVisible(true)] // ważne!
    public partial class Form1 : Form
    {
        public int zmienna = 0; // lokalna zmienna dostępna z zewnątrz (public)

        public Form1()
        {

            InitializeComponent();
            webBrowser1.Navigate(@"test.htm"); // test.htm zawiera przykładową treść podaną w pierwszym wątku
            webBrowser1.ObjectForScripting = this; // przypisanie tej klasy (this) do "window.external" w skrypcie

        }

	// funkcja po naciśnięciu przycisku
        private void button1_Click(object sender, EventArgs e)
        {
		try
		{
			// pobranie "unmanaged window"
			IHTMLWindow2 window = (IHTMLWindow2)webBrowser1.Document.Window.DomWindow;

			// odpalenie skryptu, który przypisze do lokalnej zmiennej "this.zmienna"
			// wartości ze skryptu "window.zmienna" (window.external odnosi się do tej klasy)
			window.execScript("window.external.zmienna = zmienna", "javascript");

			// w ten sam sposób możesz odpalić dowolną funkcję tej klasy
			// (lub innej przypisanej do ObjectForScripting)
			// lub robić różne inne cuda. warunek - zmienne lub metody muszą być "public",
			// a klasa musi mieć być widoczna przez COM (ustawione ComVisible(true))

			MessageBox.Show("Wartość zmiennej to: " + zmienna);
		}
		catch
		{
			// wystąpił błąd
			MessageBox.Show("Wystąpił błąd");
		}
        }
    }
}

zakładam że nie mamy dostępu do treści strony, bo jeżeli mamy to jest to dużo łatwiejsze

0
MSM napisał(a)

Nie chciałbym siać defetyzmu, ale...

<html>
<head></head>
<body>

OCENY:
Łukasz asd = 4;</li>
Zofia bla = 3;</li>
Ania zmienna = 4;</li>
</ul>
</body></p>
</html> ``` > > ;-P

A że tak spytam: gdzie tutaj jest JavaScript?? o_O

@niktmnienielubi:
Dzięki, kod działa super, dobrze wyciąga zmienną której potrzebuję :-) Ale mam jeszcze takie pytanie: co zrobić żeby ta zmienna
public int zmienna = 0; // lokalna zmienna dostępna z zewnątrz (public)

mogła być w innej klasie niż WebBrowser (poza formą)??

1

@up nie zrozumiałeś - dla takiej strony kod zwróciłby 4 ("Ania zmienna = 4") mimo że właśnie javascriptu nie ma i powinien się wywalić albo rzucić wyjątek...

Ale mam jeszcze takie pytanie: co zrobić żeby ta zmienna

A nie jest? :|

PS. @niktmnienielubi - mam nadzieję że zdajesz sobię sprawę że używanie zmiennych publicznych jest baaaardzo niezalecane? [q:ciach-bezsens]

0
MSM napisał(a)

@up nie zrozumiałeś - dla takiej strony kod zwróciłby 4 ("Ania zmienna = 4") mimo że właśnie javascriptu nie ma i powinien się wywalić albo rzucić wyjątek...

Nie wiem czy dobrze zrozumiałem... ale problem jest w tym że moja zmienna w JS zmienia się chwilę po wczytaniu strony i praktycznie nie można pobrać jej wartości z htmla... Próbowałem tak na różne sposoby ale nie wychodziło dlatego napisałem tutaj.

MSM napisał(a)

A nie jest? :|

Nie doczytałeś :P

Gość. napisał(a)

co zrobić żeby ta zmienna
public int zmienna = 0; // lokalna zmienna dostępna z zewnątrz (public)

mogła być w innej klasie niż WebBrowser (poza formą)??

1

Nie doczytałeś :P

Doczytałem, tylko nie wkleiłem całości ;)

Zmienna jest publiczna. Jest dostępna z poziomu każdej klasy .NET (czyli wszystkich).

Może chodzi o to że próbujesz się do niej odwołać przez
Form1.zmienna...

Tak nie można - potrzebujesz referencji.

Jeśli nie tak to napisz jak ją wywołujesz i z czego.

0

Tak ja wiem że jest publiczna a co za tym idzie jest dostępna dla innych klas... Ale mi chodzi o to aby była zadeklarowana w osobnej klasie niż webbrowser. Jak próbuję tak robić to wtedy nie działa ta linia (a konkretnie wywala błąd js w webbrowser):
window.execScript("window.external.zmienna = zmienna", "javascript");

0

dajesz ją do drugiej klasy

[ComVisible(true)]
class DrugaKlasa
{
	public int zmienna = 0;

}

a do webbrowser przypisujesz

webBrowser1.ObjectForScripting = InstancjaDrugiejKlasy;

jakbyś przeczytał komentarze to byś wiedział ;)

@msm: to może podasz w końcu swoje, w pełni poprawne rozwiązanie zamiast się czepiać?

1

@niktmnienielubi:

Używamy właściwości:

public int Zmienna
{get; set;}

co jest równoważnikiem tego:

private int zmienna = 0;

public int Zmienna
{
    get {return zmienna; }
    set {zmienna = value;}
}

Do dobrych zwyczajów [q:ciach-bezsens] programowania obiektowego należy ukrywanie pól klasy przed obiektami zewnętrznymi.

0

a jak to się ma do problemu z wątku? dla mnie to jest czepianie się na siłę

0

Przeczytałem komentarze do kodu i to dokładnie, ale mój kod jest dość skomplikowany a tutaj na forum przedstawiłem go w dużym uproszczeniu. Udało mi się i już wszystko pięknie działa, nie wiem dlaczego wcześniej mi nie działało, coś gdzieś musiałem pierniczyć.. :P no w każdym razie problem rozwiązany, dzięki niktmnienielubi

0
MSM napisał(a)

PS. @niktmnienielubi - mam nadzieję że zdajesz sobię sprawę że używanie zmiennych publicznych jest baaaardzo niezalecane? Praktycznie zabronione.

Nie jest, najlepszym dowodem jest to, że istnieją. Twórcy C# słyną z nieuwzględniania fajnych rzeczy, które uważają za złe. Skoro fieldy moga być publiczne, to mogą byc publiczne. Jak ktoś ich chce używac - niech to robi. Może się kiedyś np. przy databindingu zdziwi, cóż. Zabronione nie jest, nawet praktycznie.

Zastanów się: w czym Field jest gorszy od Property/Auto? Jedyne dwie roznice to to, ze mozesz do niego wziac ref/out, oraz ze jest zawsze read/write. Jesli robisz pelne autoproperty tzn. z oboma get/set public, to zostaje juz tylko jedna roznica. Zreszta, kurna, wyobrazasz sobie struct'y z autoproperties zamiast public field'ow?? Jesli tak, to chyba zapomniales po co sa w ogole struct'y..

btw. Nie polemizuj. Na te dyskusje jest dzial IO. Moj post dementuje bzdety które starasz sie wmówic językowi

1

Nie jest, najlepszym dowodem jest to, że istnieją.

Wszystkie publiczne zmienne w bibliotece standartowej są readonly - to co innego.

Zastanów się: w czym Field jest gorszy od Property/Auto?

Oczywiście jeśli w twoim projekcie zmienią się nagle założenia i będziesz potrzebował zmienić coś w sposobie dostępu do zmiennej publicznej to będziesz wprowadzał zmiany w każdym miejscu programu? Bo ja zmienię tylko kod do gettera.

btw. Nie polemizuj.

Sorry, nie mogłem się powstrzymać ;( Najwyżej niech ktoś usunie moje posty...

0
MSM napisał(a)

Nie jest, najlepszym dowodem jest to, że istnieją.

Wszystkie publiczne zmienne w bibliotece standartowej są readonly - to co innego.

bo taka mają semantykę. czytaj uważnie, napisałem: struct. to jest miejsce, gdzie nie mozesz ot tak sobie żonglowac properties'ami. w class dzieki JIT za przeproszeniem srał pies czy masz field czy autoproperty, JIT i tak to zinlineuje, jedynie w reflection bedzie to inaczej opisane i ew. stacktrace bedzie inny. zreszta co ja pisze, jaki stack trace przy autoproperty.. na dobra sprawe autoproerty maja sens istnienia lepszy niz field'y tylko dla reflection->databindingu, albo by wprowadzac polowiczne visibility inne niz public: public X{get;private set;} na przyklad.. jesli robisz full-public-auto-property, serio, w wiekszosci przypadkow field bylby rownie dobry*).

MSM napisał(a)

Zastanów się: w czym Field jest gorszy od Property/Auto?

Oczywiście jeśli w twoim projekcie zmienią się nagle założenia i będziesz potrzebował zmienić coś w sposobie dostępu do zmiennej publicznej to będziesz wprowadzał zmiany w każdym miejscu programu? Bo ja zmienię tylko kod do gettera.

Co Ty zrobisz, mnie osobiście grzeje latem i chłodzi w zimie. To co Ty zrobisz, nie decyduje o tym co jest zakazane/dozwolone/zalecane. Jakbyś u mnie wszedzie bezsensownie wciskal property, to bym Cie wywalil z projektu. Jakbyś w miejscach gdzie powinny być property wciskał Fieldy oraz poboczne metody rodem z get/set, to bym Cie wywalil z projektu. Jesli uzywalbys X w miejscu gdzie mozna uzywac X albo Y, spox, można tak i można tak. Jest wybór, nie ma zakazu.

*) Odnosząc się zaś do przytoczonej sytuacji, w tym momencie zmienil"bym" field 'public string Dupa;' na property 'public string Dupa{get{...}set{...}}' i niczego w kodzie zmieniac "bym" nie musial, poza ZEREM..DWOMA miejcami gdzie ewentualnie z racji gadania z czyms niezarzadzanym uzylem 'ref'/'out'.. Property zostaly w jezyku osadzone tak, aby byly maksymalnie nieodroznialne od ..field'ow. Nie vice-versa!!

I proszę, zanim zaczniesz dalej dyskutować, zwróć uwagę, że to co napisałem NIE twierdzi że należy stosować field'y zamiast properties i nie próbuje udowaniać wyższości tychże nad tamtymi. W kontekście projektowania interfejsów, w większości się z Toba zgadzam. Nie można natomiast wmawiać ludziom jakichś wydumanych kategorycznych zakazów. Jeśli to byłoby zakazane, kompilator by to odrzucił, albo w ogóle w języku nie poprawna byłaby składna public+field bez readonly.

0

Skoro można używać goto, to można używać goto - niby prawda, ale to nadal kiepski argument. ;)

Szczerze mówiąc - nigdy nie widziałem publicznego pola w żadnym projekcie, w którym brałem udział. Być może przyczyną jest właśnie ta konwencja, że w .NET takich rzeczy się nie spotyka.

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