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??
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??
popatrz co siedzi w WebBrowser.Document, cos sensownego powinienes z tej wlasciwosci wyciagnac
Już zanim tu napisałem to przepatrzyłem... i nic nie znalazłem... :( Jakieś pomysły?
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");
}
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
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
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ą)??
@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]
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ą)??
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.
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");
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ć?
@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.
a jak to się ma do problemu z wątku? dla mnie to jest czepianie się na siłę
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
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
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...
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.
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.