<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>webbrowser Archive - Robert Skibbe</title>
	<atom:link href="https://robbelroot.de/blog/tag/webbrowser/feed/" rel="self" type="application/rss+xml" />
	<link></link>
	<description>alias RobbelRoot – Freelance Full Stack Developer .NET</description>
	<lastBuildDate>Wed, 02 Mar 2022 10:38:53 +0000</lastBuildDate>
	<language>de</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://robbelroot.de/wp-content/uploads/2020/12/cropped-favicon-32x32.png</url>
	<title>webbrowser Archive - Robert Skibbe</title>
	<link></link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>&#x1f310; VB NET Webbrowser Alternative</title>
		<link>https://robbelroot.de/blog/vb-net-webbrowser-alternative/</link>
					<comments>https://robbelroot.de/blog/vb-net-webbrowser-alternative/#comments</comments>
		
		<dc:creator><![CDATA[Robert Skibbe]]></dc:creator>
		<pubDate>Sat, 05 Feb 2022 03:22:03 +0000</pubDate>
				<category><![CDATA[Allgemein]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Visual Basic .NET]]></category>
		<category><![CDATA[Visual Basic .NET Problemlösungen]]></category>
		<category><![CDATA[alt]]></category>
		<category><![CDATA[alternative]]></category>
		<category><![CDATA[browser]]></category>
		<category><![CDATA[chrome]]></category>
		<category><![CDATA[chromium]]></category>
		<category><![CDATA[control]]></category>
		<category><![CDATA[ersetzen]]></category>
		<category><![CDATA[modern]]></category>
		<category><![CDATA[neu]]></category>
		<category><![CDATA[steuerelement]]></category>
		<category><![CDATA[vb]]></category>
		<category><![CDATA[vb.net]]></category>
		<category><![CDATA[vbnet]]></category>
		<category><![CDATA[visual basic net]]></category>
		<category><![CDATA[webbrowser]]></category>
		<guid isPermaLink="false">https://robbelroot.de/?p=8484</guid>

					<description><![CDATA[<p>Eine VB NET Webbrowser Alternative verwenden Du möchtest eine VB NET Webbrowser Alternative installieren und einfach verwenden? Endlich dem mehr als veralteten Webbrowser Lebewohl sagen!? Dann bist Du in meinem heutigen Beitrag genau richtig! Es war einmal.. Es war einmal ein veralteter Browser, Welcher leider langsam und fehleranfällig war. Er &#8230;</p>
<p>Der Beitrag <a href="https://robbelroot.de/blog/vb-net-webbrowser-alternative/">&#x1f310; VB NET Webbrowser Alternative</a> erschien zuerst auf <a href="https://robbelroot.de">Robert Skibbe</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-image size-full"><a href="https://robbelroot.de/wp-content/uploads/2022/02/VB-NET-Webbrowser-Alternative.jpg"><img fetchpriority="high" decoding="async" width="1200" height="628" src="https://robbelroot.de/wp-content/uploads/2022/02/VB-NET-Webbrowser-Alternative.jpg" alt="" class="wp-image-8488"/></a></figure>






<h2 class="wp-block-heading" id="eine-vb-net-webbrowser-alternative-verwenden">Eine VB NET Webbrowser Alternative verwenden</h2>



<p>Du <strong>möchtest </strong>eine <strong>VB NET Webbrowser Alternative</strong> installieren und einfach verwenden? <strong>Endlich </strong>dem mehr als <strong>veralteten Webbrowser Lebewohl </strong>sagen!? Dann bist Du in meinem <strong>heutigen Beitrag </strong>genau <strong>richtig</strong>!</p>



<h3 class="wp-block-heading" id="es-war-einmal">Es war einmal..</h3>



<p>Es <strong>war </strong>einmal ein <strong>veralteter Browser</strong>, Welcher leider langsam und fehleranfällig war. Er hatte viele Probleme mit<strong> </strong>gewissen Scripten und wollte auch visuell nicht so ganz. Die <strong>modernen CSS </strong>gestylten <strong>Elemente </strong>wurden <strong>falsch dargestellt </strong>und weitere Probleme warteten. Wäre es da nicht schön, auf eine <strong>modernere Alternative </strong>zurückgreifen zu können?</p>



<p>Diese <strong>Frage </strong>habe ich mir <strong>seitdem ich </strong>ca. 2008 mit Visual Basic NET <strong>angefangen habe </strong>auch öfters <strong>gestellt</strong>. <strong>Immer wieder </strong>hat man sich dann aber doch aus fehlerhafter Gemütlichkeit <strong>mit </strong>dem <strong>alten Browser begnügt</strong>.</p>



<h3 class="wp-block-heading" id="zeit-fur-veranderung-eine-vb-net-webbrowser-alternative-muss-her">Zeit für Veränderung &#8211; Eine VB NET Webbrowser Alternative muss her</h3>



<p><strong>Irgendwann </strong>war es aber doch <strong>Zeit für Veränderung</strong>, da die Problemchen einfach zu viele wurden. <strong>Zum damaligen Zeitpunkt</strong>, bzw. in der Vergangenheit was das <strong>Upgrade zu </strong>einem guten <strong>Browser</strong>-Control <strong>nicht einfach</strong>. <strong>Zum einen </strong>musste dieser Browser natürlich <strong>einfach </strong>und <strong>intuitiv </strong>zu nutzen sein.</p>



<p><strong>Andererseits </strong>musste man die Browser-Control <strong>Alternative auch </strong>erstmal <strong>einfach installieren und konfigurieren </strong>können. Dies <strong>war </strong>zur <strong>damaligen </strong>Zeit leider <strong>nicht </strong>so <strong>prickelnd</strong>, da einige Projekte auch schnell wieder eingestampft wurden.</p>



<p><strong>Zum Glück </strong>gibt es jedoch eine <strong>Variante</strong>, Welche ich <strong>bis heute </strong>noch gerne nutze. <strong>Damit </strong>werden wir uns <strong>gleich </strong>samt <strong>Installation</strong>, <strong>Konfiguration </strong>und der <strong>ersten Website </strong>beschäftigen.</p>



<h3 class="wp-block-heading" id="das-erste-problem-die-skriptfehler">Das erste Problem &#8211; die Skriptfehler</h3>



<p><strong>Wer </strong>jemals eine <strong>Seite </strong>mit dem Webbrowser <strong>aufgerufen </strong>hat <strong>wird </strong>wissen, dass es <strong>häufig zum </strong>gleich folgenden <strong>Fehler kommt</strong>. <strong>Teilweise wird man </strong>beim Öffnen einer Seite auch richtig mit diesem und ähnlichen Fehlern <strong>vollgespammt</strong>.</p>



<figure class="wp-block-image size-full"><a href="https://robbelroot.de/wp-content/uploads/2022/02/Webbrowser-Control-Script-Problem-VB-NET-Webbrowser-Alternative.png"><img decoding="async" width="447" height="291" src="https://robbelroot.de/wp-content/uploads/2022/02/Webbrowser-Control-Script-Problem-VB-NET-Webbrowser-Alternative.png" alt="Webbrowser Control Script Problem - VB NET Webbrowser Alternative" class="wp-image-8498" title="Webbrowser Control Script Problem - VB NET Webbrowser Alternative"/></a><figcaption>Webbrowser Control Script Problem &#8211; VB NET Webbrowser Alternative</figcaption></figure>



<p>Das ist <strong>nicht nur blöd für </strong>den <strong>Nutzer</strong>, weil er alles wegklicken muss, <strong>sondern </strong>auch <strong>für uns </strong>als Entwickler. <strong>Zum Glück kann </strong>man zumindest dieses Problem <strong>durch </strong>die simple Einstellung einer <strong>Eigenschaft lösen</strong>.</p>



<p>Dazu ändert man einfach die <strong><a href="https://docs.microsoft.com/de-de/dotnet/api/system.windows.forms.webbrowser.scripterrorssuppressed?view=windowsdesktop-6.0" target="_blank" rel="noreferrer noopener">&#8222;ScriptErrorsSuppressed&#8220;-Eigenschaft </a></strong>auf &#8222;true&#8220;, <strong>entweder </strong>via <strong>Designer</strong>, <strong>oder </strong>im <strong>Code</strong>. <strong>Meistens </strong>sollten <strong>diese Boxen </strong>dann <strong>aufhören </strong>zu erscheinen und wir sind zumindest das los..</p>



<h3 class="wp-block-heading" id="nicht-mehr-unterstutzte-seiten-das-nachste-problem">Nicht mehr unterstützte Seiten &#8211; Das nächste Problem</h3>



<p><strong>Neben </strong>dem <strong>oben </strong>genannten <strong>Problem </strong>gibt es auch unter anderem <strong>noch </strong>das <strong>Nächste</strong>. Dabei <strong>handelt </strong>es <strong>sich um </strong>eine Art &#8222;<strong>nicht </strong>mehr <strong>unterstützt</strong>&#8220; <strong>Meldung</strong>, Welche man auf vielen Seiten sieht. <strong>Wer </strong>also <strong>mit </strong>der normalen <strong><a href="https://docs.microsoft.com/de-de/dotnet/api/system.windows.forms.webbrowser.navigate" target="_blank" rel="noreferrer noopener">&#8222;Navigate&#8220;-Methode</a></strong> versucht <strong>Seiten </strong>zu <strong>besuchen</strong>, bekommt <strong>immer öfter </strong>solche <strong>Meldungen </strong>hier:</p>



<figure class="wp-block-image size-full"><a href="https://robbelroot.de/wp-content/uploads/2022/02/Webbrowser-Control-nicht-mehr-unterstuetzt-VB-NET-Webbrowser-Alternative.png"><img decoding="async" width="414" height="353" src="https://robbelroot.de/wp-content/uploads/2022/02/Webbrowser-Control-nicht-mehr-unterstuetzt-VB-NET-Webbrowser-Alternative.png" alt="Webbrowser Control nicht mehr unterstützt - VB NET Webbrowser Alternative" class="wp-image-8506" title="Webbrowser Control nicht mehr unterstützt - VB NET Webbrowser Alternative"/></a><figcaption>Webbrowser Control nicht mehr unterstützt &#8211; VB NET Webbrowser Alternative</figcaption></figure>



<p><strong>Neben </strong>dem <strong>problembehafteten Öffnen </strong>von oben ist <strong>dies </strong>natürlich ein &#8222;<strong>Worst Case</strong>&#8222;-<strong>Szenario</strong>. <strong>Hier </strong>können wir dann <strong>leider </strong>gar <strong>nichts </strong>mehr <strong>tricksen </strong>und müssen <strong>vollständig </strong>davon <strong>absehen</strong>.</p>



<h3 class="wp-block-heading" id="javascript-injizieren-net-so-prickelnd">JavaScript injizieren &#8211; net so prickelnd</h3>



<p>Wer im Web-Bereich arbeitet, wird irgendwann wohl nicht um einen gewissen Bestandteil herumkommen: JavaScript. Es wird also sicherlich<strong> </strong>das ein oder andere Mal vorkommen, dass<strong> </strong>man <strong>JavaScript ausführen </strong>möchte. <strong>Ich selbst </strong>habe es schon <strong>öfters für </strong>gewisse <strong>Exports</strong>, <strong>oder </strong>eventuellen <strong>Automatisierungen </strong>verwendet.</p>



<p><strong>Leider macht </strong>es einem das <strong>normale Webbrowser</strong>-Control auch hier <strong>nicht </strong>gerade <strong>einfach</strong>. Man <strong>muss </strong>einen <strong>umständlichen Weg über </strong>die <strong>Erstellung </strong>eines Html-<strong>Elements </strong>gehen.</p>



<p><strong>Dazu </strong>muss man sich zuerst eine <strong>Referenz auf </strong>das <strong>Head</strong>-Element <strong>holen und </strong>ein <strong>neues Script</strong>-Element <strong>erstellen</strong>. <strong>Anschließend </strong>versieht man dieses <strong>Element </strong>dann <strong>mit Inhalt </strong>und <strong>fügt es </strong>dann <strong>an </strong>den <strong>Head </strong>an. <strong>Zum Schluss </strong>kann man dann z. B. eine <strong>Funktion mit </strong>Webbrowser.Document.<strong>InvokeScript</strong>(&#8222;&lt;Funktionsname>&#8220;) <strong>ausführen</strong>.</p>



<h2 class="wp-block-heading" id="die-moderne-vb-net-webbrowser-alternative">Die moderne VB NET Webbrowser Alternative</h2>



<figure class="wp-block-image size-full"><a href="https://robbelroot.de/wp-content/uploads/2022/02/VB-NET-moderne-Webbrowser-Alternative-Cefsharp.jpg"><img loading="lazy" decoding="async" width="1200" height="628" src="https://robbelroot.de/wp-content/uploads/2022/02/VB-NET-moderne-Webbrowser-Alternative-Cefsharp.jpg" alt="VB NET moderne Webbrowser Alternative Cefsharp" class="wp-image-8513" title="VB NET moderne Webbrowser Alternative Cefsharp"/></a><figcaption>VB NET moderne Webbrowser Alternative Cefsharp</figcaption></figure>



<p>Im <strong>nächsten Schritt </strong>kommen wir in diesem <strong>Tutorial </strong>an eine <strong>mögliche</strong>, moderne <strong>Alternative</strong>. Ich spreche hier <strong>wie im Bild </strong>schon <strong>angepriesen </strong>von dem <strong>tollen &#8222;CefSharp</strong>-Browser&#8220;. Dieser <strong>bringt </strong>uns alle <strong>modernen Funktionalitäten </strong>eines Browsers <strong>in </strong>unsere <strong>VB NET oder C#</strong> Anwendung.</p>



<p>Der <strong>CefSharp-Webbrowser</strong> funktioniert übrigens sowohl bei <strong>Winforms</strong>&#8211; als <strong>auch bei WPF</strong>-Anwendungen. Daher braucht man sich dort im Gegensatz zu eventuellen anderen Bibliotheken <strong>keine Sorgen </strong>machen &#8211; yay! Die Installation erfolgt – wie Du gleich sehen wirst – wirklich denkbar einfach.</p>



<h3 class="wp-block-heading" id="installation-des-neuen-webbrowsers">Installation des neuen Webbrowsers</h3>



<p><strong>Starten </strong>wir <strong>nun </strong>mit der <strong>Installation </strong>der <strong>VB NET Webbrowser Alternative</strong> von CefSharp. Dazu <strong>gehen wir in Visual Studio</strong> hin und <strong>öffnen </strong>den <strong>NuGet-Paketmanager</strong>. Er ist sozusagen das Standard-Instrument zur Verwaltung von Paketen in Visual Studio.</p>



<p>Das kannst Du natürlich entweder <strong>über </strong>das <strong>Menü </strong>oben rechts, <strong>oder über </strong>einen passenden <strong>Hotkey</strong> erledigen. <strong>Wenn </strong>Du eine <strong>grafische Unterstützung benötigst</strong>, oder bevorzugst, <strong>empfehle </strong>ich Dir den <strong>Paketmanager</strong>.</p>



<p>Alternativ können Pakete auch über die im Bild zu sehende &#8222;Paket-Manager-Konsole&#8220; installiert werden, allerdings ohne GUI. Dort verwendet man dann tatsächlich eine Art &#8222;cmd&#8220;, also eine Konsole.</p>



<p>Zum <strong>Öffnen über </strong>das <strong>Menü</strong>, findest Du den Menüpunkt <strong>hier</strong>:</p>



<figure class="wp-block-image size-full"><a href="https://robbelroot.de/wp-content/uploads/2022/02/NuGet-Paketmanager-oeffnen-VB-NET-Webbrowser-Alternative.png"><img loading="lazy" decoding="async" width="712" height="346" src="https://robbelroot.de/wp-content/uploads/2022/02/NuGet-Paketmanager-oeffnen-VB-NET-Webbrowser-Alternative.png" alt="NuGet Paketmanager öffnen - VB NET Webbrowser Alternative" class="wp-image-8521" title="NuGet Paketmanager öffnen - VB NET Webbrowser Alternative"/></a><figcaption>NuGet Paketmanager öffnen &#8211; VB NET Webbrowser Alternative</figcaption></figure>



<p><strong>Danach öffnet sich </strong>das gleich folgende <strong>Fenster</strong>, <strong>wo </strong>wir die <strong>Installation </strong>dann <strong>durchführen</strong>. <strong>Klicke </strong>im Fenster <strong>oben links auf </strong>den Reiter &#8222;<strong>Durchsuchen</strong>&#8222;, wodurch Du zu <strong>installierende Pakete finden </strong>kannst:</p>



<figure class="wp-block-image size-full"><a href="https://robbelroot.de/wp-content/uploads/2022/02/Cefsharp-fuer-Winforms-oder-WPF-installieren.png"><img loading="lazy" decoding="async" width="905" height="473" src="https://robbelroot.de/wp-content/uploads/2022/02/Cefsharp-fuer-Winforms-oder-WPF-installieren.png" alt="Cefsharp für Winforms oder WPF installieren" class="wp-image-8524" title="Cefsharp für Winforms oder WPF installieren"/></a><figcaption>Cefsharp für Winforms oder WPF installieren</figcaption></figure>



<p><strong>Wähle dann </strong>das <strong>passende Paket </strong>für deine Anwendung aus, <strong>sprich Winforms</strong>, oder <strong>WPF</strong>. <strong>Beachte hier</strong> <strong>auch </strong>ebenso, <strong>ob </strong>Du eine &#8222;<strong>Net Core</strong>&#8222;-<strong>Anwendung erstellt </strong>hast, dann brauchst Du eventuell die anderen Pakete.</p>



<p><strong>Danach kannst </strong>Du <strong>rechts außen </strong>noch das <strong>Projekt bestimmen</strong>, <strong>wo </strong>das Paket <strong>hinzugefügt </strong>werden soll. <strong>Zum Schluss </strong>kannst Du <strong>&#8222;installieren&#8220; klicken </strong>und <strong>musst ggf</strong>. einige Sekündchen <strong>warten</strong>.</p>



<p>Falls Du doch die Installation <strong>via Konsole</strong> bevorzugst, kannst Du diese beiden Befehle ausführen:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">Install-Package CefSharp.Common</pre>



<p>Dann brauchst Du noch die <strong>Winforms</strong>, bzw. <strong>WPF spezifische </strong>Installation:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">Install-Package CefSharp.WinForms
Install-Package CefSharp.Wpf</pre>



<p><strong>Beachte </strong>hierbei auch unter Umständen die &#8222;<strong>NETCore-Variante</strong>&#8222;, die Pakete gibt es jeweils auch für NETCore. Schaue dafür einfach im Paket-Manager nach, wenn Du nach &#8222;CefSharp&#8220; suchst.</p>



<style>
.info-banner {
  background: #fff9bb;
  padding: 2em;
  border-radius: 0.5em;
}
</style>



<p class="info-banner"><strong>Achtung</strong>: Bei <strong>meiner Installation </strong>für das Beispielprojekt <strong>hatte </strong>ich einige <strong>Probleme</strong>. <strong>Daher </strong>mein <strong>Tipp</strong>: <strong>Wenn </strong>Du den momentanen <strong>Projekt-Standard</strong> &#8222;.<strong>NET Core 3.1</strong>&#8220; verwendest, <strong>installiere </strong>das &#8222;<strong>Common.NetCore</strong>&#8222;-Paket <strong>zuerst</strong>. Anschließend <strong>dann </strong>das <strong>Paket für </strong>deine jeweilige &#8222;<strong>Plattform</strong>&#8222;, also Winforms, oder WPF. <strong>Falls </strong>Du <strong>dennoch Probleme </strong>haben solltest, <strong>lade </strong>Dir am besten das <strong>Beispielprojekt </strong>unten herunter.</p>



<h3 class="wp-block-heading" id="einrichtung-des-neuen-webbrowser-controls">Einrichtung des neuen Webbrowser Controls</h3>



<p>Im <strong>nächsten Step werden </strong>wir das <strong>Webbrowser</strong>-Control von CefSharp <strong>einrichten</strong>, bzw. vorbereiten. Dazu <strong>gehört einerseits</strong>, dass es auf der <strong>Form </strong>erscheint und <strong>andererseits</strong> z. B. der Session-<strong>Cache</strong>.</p>



<p><strong>Um </strong>den Chromium-<strong>Webbrowser </strong>nun <strong>auf </strong>die <strong>Form </strong>zu <strong>bekommen</strong>, gehen wir <strong>wie folgt </strong>vor:</p>



<ul class="wp-block-list"><li>Wir <strong>definieren </strong>eine <strong>Eigenschaft</strong>, o. Ä. innerhalb der Form-Klasse</li><li>Wir <strong>instanziieren </strong>diese <strong>Eigenschaft</strong></li><li>Danach <strong>setzen </strong>wir eventuelle <strong>Einstellungen</strong></li><li>Und <strong>fügen </strong>den Browser der <strong>Form hinzu</strong></li></ul>



<p><strong>Füge </strong>der Form-<strong>Klasse </strong>also nun eine <strong>neue Eigenschaft </strong>(oder Feld) vom Typ &#8222;ChromiumWebBrowser&#8220; hinzu:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="visualbasic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">Imports CefSharp.WinForms

Public Class Form1

    Public Property Wb As ChromiumWebBrowser

End Class</pre>



<p><strong>Vergiss nicht</strong>, den dafür <strong>notwendigen Import </strong>oben <strong>hinzuzufügen</strong>, sonst wirst Du einen Fehler bekommen.</p>



<p><strong>Erstelle </strong>anschließend eine <strong>kleine asynchrone Funktion</strong>, <strong>Welche </strong>uns die <strong>Konfiguration </strong>des <strong>Browsers </strong>abnimmt:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="visualbasic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">Private Async Function PrepareBrowserAsync() As Task
    ' ...
End Function</pre>



<p>Diese <strong>Funktion rufen wir </strong>dann einfach <strong>im </strong>&#8222;<strong>Load</strong>&#8222;-Ereignis auf – keine Sorge, ich <strong>erkläre alles Notwendige </strong>sofort.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="visualbasic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">Private Async Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    Await PrepareBrowserAsync()
End Sub</pre>



<h3 class="wp-block-heading" id="inhalte-der-hilfs-methode">Inhalte der Hilfs-Methode</h3>



<p><strong>Im ersten Schritt </strong>dieser Methode werden wir uns um den <strong>Cache des Browsers</strong> kümmern. Das <strong>machen wir</strong>, damit <strong>eventuelle Popups </strong>a la &#8222;Bitte Cookies bestätigen blabla&#8220; <strong>nicht jedes Mal </strong>beim Start kommen. <strong>Je</strong> <strong>nach Anforderungen </strong>deinerseits, kannst Du es natürlich <strong>auslassen</strong>.</p>



<p><strong>Zuerst müssen </strong>wir dafür erstmal <strong>sicherstellen</strong>, <strong>dass </strong>das notwendige <strong>Verzeichnis </strong>für den Cache <strong>existiert</strong>:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="visualbasic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">Dim cachePath = IO.Path.Combine(Environment.CurrentDirectory, "cache")
If Not IO.Directory.Exists(cachePath) Then
    IO.Directory.CreateDirectory(cachePath)
End If</pre>



<p>Danach <strong>legen </strong>wir <strong>Einstellungen </strong>für die &#8222;Cef-Umgebung&#8220; <strong>fest</strong>, Welche <strong>durch </strong>eine <strong>statische Methode </strong>geladen werden. Wir <strong>aktivieren </strong>die <strong>Session-Cookies</strong> und <strong>legen </strong>den <strong>Pfad für </strong>den <strong>Cache </strong>fest:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="visualbasic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">Dim settings = New CefSettings() With {
    .PersistSessionCookies = True,
    .CachePath = cachePath
}
Cef.Initialize(settings)</pre>



<p><strong>Zuletzt instanziieren wir </strong>die vorher definierte &#8222;<strong>Wb</strong>&#8222;-<strong>Eigenschaft </strong>und <strong>fügen </strong>die <strong>Browser-Instanz</strong> einem Panel auf der Form <strong>hinzu</strong>.</p>



<h3 class="wp-block-heading" id="wart-mal-ne-sekunde">Wart&#8216; mal ne Sekunde..</h3>



<p><strong>Danach </strong>lasse ich die <strong>Funktion nochmal </strong>eine halbe Sekunde asynchron <strong>warten</strong>. Das <strong>musste ich </strong>in meinem Beispiel <strong>machen</strong>, <strong>damit </strong>das <strong>Laden der </strong>anschließenden <strong>Adresse funktionierte</strong>.</p>



<p>Hier <strong>gibt </strong>es <strong>vermutlich noch bessere Alternativen</strong>, aber ich denke das passt hier an der Stelle. Du <strong>kannst </strong>ja mal <strong>probieren</strong>, das <strong>Warten wegzulassen</strong>, falls Du <strong>nicht direkt </strong>nach dem Start des Programmes eine Adresse lädst. <strong>Melde Dich </strong>dann gerne in der Kommentar-Sektion!</p>



<pre class="EnlighterJSRAW" data-enlighter-language="visualbasic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">Wb = New ChromiumWebBrowser("") With {
    .Dock = DockStyle.Fill
}
pnlWebbrowserContainer.Controls.Add(Wb)
Await Task.Delay(500)</pre>



<h3 class="wp-block-heading" id="die-komplette-hilfs-funktion">Die komplette Hilfs-Funktion</h3>



<pre class="EnlighterJSRAW" data-enlighter-language="visualbasic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">Private Async Function PrepareBrowserAsync() As Task
    Dim cachePath = IO.Path.Combine(Environment.CurrentDirectory, "cache")
    If Not IO.Directory.Exists(cachePath) Then
        IO.Directory.CreateDirectory(cachePath)
    End If
    Dim settings = New CefSettings() With {
        .PersistSessionCookies = True,
        .CachePath = cachePath
    }
    Cef.Initialize(settings)
    Wb = New ChromiumWebBrowser("") With {
        .Dock = DockStyle.Fill
    }
    Await Task.Delay(500)
    pnlWebbrowserContainer.Controls.Add(Wb)
End Function</pre>



<h3 class="wp-block-heading" id="das-ganze-sauber-schliessen">Das Ganze sauber schließen</h3>



<p><strong>Zum Schluss</strong> könnte man noch im &#8222;<strong>FormClosing</strong>&#8222;-Ereignis die – ich nenne Sie mal – &#8222;Cef-Engine&#8220; sauber schließen. <strong>Dafür rufst </strong>Du einfach die <strong>statische </strong>&#8222;<strong>Shutdown</strong>&#8222;-Methode der Cef-Klasse <strong>auf</strong>.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="visualbasic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing
    Cef.Shutdown()
End Sub</pre>



<h2 class="wp-block-heading" id="basis-funktionalitaten-der-vb-net-webbrowser-alternative">Basis-Funktionalitäten der VB NET Webbrowser Alternative</h2>



<figure class="wp-block-image size-full"><a href="https://robbelroot.de/wp-content/uploads/2022/02/Cefsharp-Funktionalitaeten-als-Alternativer-Webbrowser-Control.jpg"><img loading="lazy" decoding="async" width="1200" height="628" src="https://robbelroot.de/wp-content/uploads/2022/02/Cefsharp-Funktionalitaeten-als-Alternativer-Webbrowser-Control.jpg" alt="Cefsharp Funktionalitäten als Alternativer Webbrowser Control" class="wp-image-8555" title="Cefsharp Funktionalitäten als Alternativer Webbrowser Control"/></a><figcaption>Cefsharp Funktionalitäten als Alternativer Webbrowser Control</figcaption></figure>



<p><strong>Nachdem </strong>wir <strong>nun </strong>den <strong>CefSharp </strong>ChromiumWebBrowser <strong>aufgesetzt </strong>haben, können wir uns <strong>nun an </strong>die <strong>Funktionalität </strong>machen. Die <strong>einfachste Funktionalität</strong>, die man jetzt vermutlich sehen möchte ist: Wie <strong>rufe </strong>ich eine <strong>URL auf</strong>!? Wir <strong>werden </strong>uns <strong>gleich </strong>außerdem <strong>anschauen</strong>, wie man <strong>verschiedene JavaScript-Scripts </strong>ausführen kann.</p>



<h3 class="wp-block-heading" id="eine-url-aufrufen">Eine URL aufrufen</h3>



<p>Die <strong>erste und </strong>wohl <strong>bekannteste Aufgabe </strong>eines Browsers <strong>ist </strong>vermutlich das <strong>Aufrufen </strong>einer <strong>Webadresse</strong>. Wir <strong>schauen </strong>uns also <strong>diese Grundfunktionalität </strong>als <strong>allererstes </strong>an. Der <strong>ChromiumWebBrowser verwendet statt </strong>der vom normalen Webbrowser bekannten &#8222;<strong>Navigate</strong>&#8222;-Methode <strong>eine Andere</strong>.</p>



<p>Beim <strong>CefShap-Browser</strong> handelt es sich dabei um <strong>diese Methoden </strong>hier:</p>



<ul class="wp-block-list"><li><strong>LoadUrl</strong></li><li><strong>LoadUrlAsync</strong></li><li><strong>LoadUrlWithPostData</strong></li></ul>



<p><strong>Wenn </strong>wir nun <strong>also </strong>eine <strong>URL laden</strong> wollen, kann das <strong>wie </strong>gleich <strong>folgend </strong>aussehen. <strong>Beachte </strong>hier noch meine <strong>Hinweise bezüglich </strong>der &#8222;<strong>PrepareBrowserAsync</strong>&#8222;-Methode oben.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="visualbasic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">Private Async Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    Await PrepareBrowserAsync()
    Await Wb.LoadUrlAsync("https://google.de")
End Sub</pre>



<h3 class="wp-block-heading" id="javascript-code-ausfuhren">JavaScript-Code ausführen</h3>



<p>Die <strong>nächst wichtigste Funktionalität </strong>wird das <strong>Ausführen von JavaScript-Code</strong> innerhalb des Browsers sein. <strong>Statt </strong>wie im alten Webbrowser-Control irgendwelche <strong>Elemente zu </strong>&#8222;<strong>injecten</strong>&#8222;, <strong>können </strong>wir die <strong>Scripts </strong>hier einfach <strong>direkt ausführen</strong>. <strong>Dazu verwende </strong>ich zum Beispiel die &#8222;<strong>EvaluateScriptAsync</strong>&#8222;-Funktion <strong>regelmäßig</strong>.</p>



<p>Wenn Du <strong>genauere Details </strong>haben möchtest, solltest Du <strong><a href="https://cefsharp.github.io/" target="_blank" rel="noreferrer noopener">die Dokumentation aufsuchen</a></strong>.</p>



<p>Grundsätzlich <strong>gibt </strong>es dort <strong>2 wichtige Überladungen</strong>:</p>



<ul class="wp-block-list"><li>der <strong>Aufruf mit</strong> dem &#8222;<strong>Methoden</strong>-Namen&#8220; <strong>und </strong>den <strong>Parametern</strong></li><li>und ein <strong>Aufruf des Scripts an sich</strong></li></ul>



<h4 class="wp-block-heading" id="einen-klick-auf-einen-button-simulieren">Einen Klick auf einen Button simulieren</h4>



<p>Führen wir im <strong>nächsten Schritt </strong>einfach mal einen <strong>Code </strong>aus, <strong>Welcher </strong>einen &#8222;<strong>Button</strong>-Click&#8220; simuliert:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="visualbasic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">Await Wb.EvaluateScriptAsync("document.querySelector('#theButtonId').click();")</pre>



<p>Um <strong>Informationen über </strong>die <strong>Ausführung </strong>dieses Codes zu bekommen, <strong>können </strong>wir den <strong>Rückgabewert nutzen</strong>.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="visualbasic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">Dim response = Await Wb.EvaluateScriptAsync("document.querySelector('#theButtonId').click();")</pre>



<p><strong>Danach </strong>können wir <strong>prüfen</strong>, <strong>ob </strong>alles in <strong>Ordnung </strong>gelaufen ist:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="visualbasic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">If response.Success Then
  ' ...
End If</pre>



<p><strong>Anschließend können </strong>wir <strong>an </strong>die eventuell zurückgegebenen <strong>Daten kommen</strong>. Es <strong>könnte </strong>ja zum Beispiel sein, dass wir <strong>geprüft </strong>haben, <strong>ob </strong>ein <strong>gewisses Element existiert</strong>:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="visualbasic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">Dim response = Await Wb.EvaluateScriptAsync("(function () { return document.querySelector('#theId') !== null; })();")
If Not response.Success Then
  ' early return..
  Return
End If
Dim elementExists = response.ToString().ToLower() = "true"</pre>



<p><strong>Dazu </strong>habe ich hier eine &#8222;<strong>Self-Executing-Function</strong>&#8220; in JavaScript gebaut, <strong>Welche </strong>dann &#8222;<strong>true</strong>&#8220; <strong>oder </strong>&#8222;<strong>false</strong>&#8220; zurückgibt. In der <strong>letzten Zeile </strong>haben wir dann die <strong>Rückgabe getestet</strong>.</p>



<h4 class="wp-block-heading" id="warten-bis-ein-element-vorhanden-ist">Warten bis ein Element vorhanden ist</h4>



<p>Ich denke im <strong>nächsten Schritt</strong>, <strong>können </strong>wir eines der vorherigen <strong>Beispiele </strong>ein wenig <strong>erweitern</strong>. Wir <strong>haben zwar </strong>im letzten Beispiel <strong>prüfen </strong>können, <strong>ob </strong>ein gewisses <strong>Element existiert</strong>, aber.. <strong>Leider konnten </strong>wir <strong>nicht </strong>aktiv <strong>warten</strong>, <strong>bis </strong>das Element dann tatsächlich <strong>vorhanden </strong>ist.</p>



<p>Dies <strong>wird allerdings </strong>– zumindest aus meiner Erfahrung heraus – ein sehr <strong>wichtiger Bestandteil </strong>vieler webbrowser-basierter Anwendungen <strong>sein</strong>. <strong>Möchten </strong>wir beispielsweise ein <strong>Formular ausfüllen</strong>, <strong>müssen </strong>wir natürlich <strong>warten</strong>, <strong>bis </strong>Dieses <strong>sichtbar </strong>ist. Das wirst Du auch weiter unten im Autologin-Beispiel verwenden können.</p>



<p>Eine <strong>mögliche Vorgehensweise </strong>dafür, kannst Du Dir in der gleich <strong>folgenden</strong> Funktion ansehen. <strong>Eventuell möchtest </strong>Du die Funktion ja auch <strong>als Erweiterung definieren</strong>, je nachdem wie es Dir besser passt.</p>



<h5 class="wp-block-heading" id="die-funktion-und-erklarungen">Die Funktion und Erklärungen</h5>



<p>Hier aber <strong>erst einmal </strong>die <strong>Funktion und </strong>vorerst die <strong>Erklärungen </strong>zu den einzelnen Anweisungen. <strong>Zuerst initialisieren </strong>wir eine <strong>Variable </strong>namens &#8222;<strong>timeoutReached</strong>&#8222;, mit dem &#8222;booleschen False&#8220;. Somit <strong>bekommt </strong>die Variable auch über <strong>Typinferenz </strong>dessen <strong>Datentyp </strong>(also Boolean).</p>



<p><strong>Danach merken </strong>wir uns in &#8222;started&#8220;, <strong>wann </strong>unser Such-<strong>Durchlauf gestartet </strong>wurde. Das <strong>wird </strong>gleich noch <strong>für </strong>eine <strong>Timeout</strong>-Funktionalität <strong>relevant</strong>. <strong>Ebenso benötigen </strong>wir eine <strong>Variable</strong>, <strong>um </strong>das <strong>Ergebnis </strong>der Javascript-Ausführung <strong>zwischen </strong>zu <strong>speichern</strong>. <strong>Anschließend </strong>kommt noch die <strong>Variable</strong>, <strong>um </strong>das notwendige <strong>Javascript</strong>-Skript zu speichern.</p>



<p>Dort <strong>ergänzen </strong>wir die <strong>Funktionalität </strong>der &#8222;<strong><a href="https://developer.mozilla.org/de/docs/Web/API/Document/querySelector" target="_blank" rel="noreferrer noopener">document.querySelector</a></strong>&#8222;-Funktion <strong>um </strong>den dynamischen <strong>Parameter </strong>&#8222;selector&#8220;. Das <strong>machen </strong>wir, <strong>damit </strong>unsere <strong>VB-Funktion dynamisch </strong>auf ein Element via CSS-Selektor <strong>warten kann</strong>.</p>



<h5 class="wp-block-heading" id="die-schleife-zur-prufung">Die Schleife zur Prüfung</h5>



<p><strong>Nun </strong>kommt die &#8222;Do&#8220;-<strong>Schleife</strong>, Welche im Endeffekt<strong> </strong>immer wieder diese Punkte hier durcharbeitet:</p>



<ul class="wp-block-list"><li><strong>hole </strong>das <strong>Ergebnis </strong>des Skripts aus dem Browser</li><li><strong>wenn </strong>die <strong>Rückgabe </strong>der &#8222;EvaluateScriptAsync&#8220;-Funktion &#8222;.<strong>Success</strong>&#8220; auf &#8222;True&#8220; ist <strong>und </strong>&#8222;.Result&#8220; <strong>nicht </strong>&#8222;<strong>Nothing</strong>&#8220; ist..</li><li><strong>dann verarbeite </strong>die Ausgabe von JavaScript <strong>und falls </strong>diese &#8222;<strong>True</strong>&#8220; ergibt, <strong>gebe </strong>selbst &#8222;<strong>True</strong>&#8220; zurück, <strong>da </strong>das <strong>Element gefunden </strong>wurde</li><li><strong>andernfalls </strong>ginge der Schleifendurchlauf <strong>weiter</strong>, <strong>wo </strong>das <strong>Timeout geprüft </strong>wird</li><li>und gewartet wird &#8211; <strong>falls </strong>dann am Ende das <strong>Timeout erreicht </strong>wird, <strong>verlassen </strong>wir mit &#8222;<strong>False</strong>&#8222;</li><li>Dieser Schritt <strong>wird </strong>dementsprechend <strong>übersprungen</strong>, <strong>wenn </strong>das <strong>Timeout </strong>auf &#8222;<strong>kleiner gleich</strong>&#8220; <strong>0</strong> eingestellt wird.</li></ul>



<pre class="EnlighterJSRAW" data-enlighter-language="visualbasic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">    Private Async Function WaitForElementAsync(selector As String, Optional timeout As Integer = 4000, Optional waitInterval As Integer = 500) As Task(Of Boolean)
        Dim timeoutReached = False
        Dim started = Date.Now
        Dim result As JavascriptResponse
        Dim checkElementScript = "
            (function () {
                var element = document.querySelector('" &amp; selector &amp; "');
                return element !== null;
            })();"
        Do
            result = Await Wb.EvaluateScriptAsync(checkElementScript)
            If result.Success AndAlso result.Result IsNot Nothing Then
                dim jsResultText = result.Result.ToString()
                Dim elementFound = Boolean.Parse(jsResultText)
                If elementFound Then Return True
            End If
            If timeout > 0 Then
                timeoutReached = (Date.Now - started).TotalMilliseconds >= timeout
            End If
            Await Task.Delay(waitInterval)
        Loop While Not timeoutReached
        Return False
    End Function</pre>



<h2 class="wp-block-heading">Einen kleinen Autologin umsetzen</h2>



<p><strong>Nachdem </strong>ich nun seit <strong>einiger Zeit </strong>auf diesen Blogpost <strong>zurückblicke</strong>, dachte ich mir: &#8222;Da <strong>muss noch was </strong>rein&#8220;. Schon <strong>allein </strong>aus dem <strong>Grund</strong>, <strong>dass </strong>das <strong>Webbrowser </strong>hier und da halt <strong>immer mal wieder</strong> zum Einsatz kommt.</p>



<p><strong>Grundsätzlich </strong>denkt man dann meiner Erfahrung nach <strong>früher oder später</strong> über die <strong>Automation </strong>gewisser Prozesse nach. Ich meine <strong>wer hat schon Lust</strong> alles im Sinne der &#8222;<strong>Monkey</strong>&#8211;<strong>Work</strong>&#8220; selbst zu machen. Unsere <strong>Zeit ist</strong> schließlich <strong>kostbar </strong>und als <strong>Entwickler </strong>sind wir ja <strong>meist </strong>&#8222;<strong>faul</strong>&#8220; &#8211; eher innovativ/kreativ.</p>



<p><strong>Daher </strong>dachte ich mir, ich <strong>mache </strong>mal einen <strong>kleinen Autologin, </strong>also eine durch <strong>Programm</strong>-Code durchgeführte <strong>Anmeldung </strong>als Beispiel. Der <strong>Browser soll </strong>also eine gewisse <strong>Webseite öffnen und </strong>dann eine automatisierte <strong>Anmeldung </strong>durchführen. <strong>Zum Glück </strong>ist das mit unserer <strong>VB NET Webbrowser Alternative</strong> überhaupt <strong>nicht schwer</strong>!</p>



<p><strong>Oben </strong>habe ich ja auch <strong>schon </strong>ein wenig <strong>gezeigt</strong>, davon <strong>können </strong>wir dann noch nochmal <strong>Gebrauch machen</strong>. <strong>Ganz speziell </strong>ist natürlich jetzt <strong>JavaScript </strong>am Zug, da wir <strong>hiermit </strong>die <strong>clientseitigen </strong>Aspekte <strong>manipulieren </strong>können. Dabei <strong>spreche </strong>ich <strong>von </strong>den <strong>Eingabefeldern </strong>einer Form <strong>und </strong>z. B. das Abschicken des Login-Formulars.</p>



<p>Die <strong>Eingabefelder müssen </strong>mit unseren Anmeldedaten <strong>befüllt und </strong>der &#8222;Anmelde&#8220;-<strong>Knopf geklickt </strong>werden. Danach geht der Web-Flow seinen üblichen Weg, also die Form wird dadurch an den Server geschickt und verarbeitet.</p>



<p>Dazu <strong>werde </strong>ich hier auch zwei wirklich einfache <strong>PHP-Scripts bereitstellen</strong>. Diese <strong>kannst </strong>Du dann auf Deinen Webspace <strong>hochladen, </strong>oder mit einem lokalen Webserver in Eigenregie <strong>testen</strong>. Beachte, dass ich die Skripte nach der Erledigung des Tutorials wieder von meinem Webspace lösche. Es könnte also sein, dass eventuelle URLs nicht mehr aufrufbar sind.</p>



<h3 class="wp-block-heading">Die PHP-Skripte für die Server-Seite</h3>



<p><strong>Bevor </strong>wir uns nun an die Ausführung von irgendwelchem <strong>Visual Basic NET Code</strong> machen, müssen wir erstmal die <strong>Server-Seite abhaken</strong>. Ansonsten hätten wir keine Möglichkeit das Ganze – meiner Meinung nach –sinnig zu testen. Dafür verwenden wir wie bereits angekündigt 2 simple PHP-Skripte:</p>



<ul class="wp-block-list"><li>login.php – Die Login-Seite</li><li>index.php – Der &#8222;geschützte&#8220; Bereich</li></ul>



<h4 class="wp-block-heading">Das &#8222;login.php&#8220;-Skript zur Anmeldung</h4>



<figure class="wp-block-image size-full"><a href="https://robbelroot.de/wp-content/uploads/2022/03/VB-NET-Webbrowser-Autologin-Automation.png"><img loading="lazy" decoding="async" width="264" height="163" src="https://robbelroot.de/wp-content/uploads/2022/03/VB-NET-Webbrowser-Autologin-Automation.png" alt="VB NET Webbrowser Autologin - Automation" class="wp-image-9786" title="VB NET Webbrowser Autologin - Automation"/></a><figcaption>VB NET Webbrowser Autologin &#8211; Automation</figcaption></figure>



<p>Kümmern wir uns <strong>im ersten Schritt</strong> der serverseitigen Programmierung um das <strong>Login-Skript</strong> selbst. Im Endeffekt haben wir einen <strong>HTML5 Standard-Aufbau</strong>, <strong>mit </strong>ein wenig <strong>PHP und </strong>Styling-Informationen via <strong>CSS</strong>.</p>



<p>Eigentlich relativ überflüssig zu erwähnen – vermutlich jedenfalls – aber dennoch: Bedenke bitte, dass es sich hierbei um Beispiel-Code speziell für die Demo handelt. Gehe <strong>bitte nicht </strong>hin und <strong>speichere </strong>irgendwelche <strong>Zugangsdaten </strong>hardcoded in produktiven Skripten.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="php" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">&lt;?php
session_start();

$loggedIn = isset($_SESSION['loggedin']);
$loggedOut = false;
if (isset($_GET['logout']) &amp;&amp; $loggedIn) {
  unset($_SESSION['loggedin']);
  $loggedOut = true;
}

if ($loggedIn) {
  header('Location: index.php');
  die();
}

$loginAttempted = isset($_POST['login']);
// ONLY FOR THE DEMO!!!
$user = 'benutzer';
$password = 'passwort';
if ($loginAttempted) {
  $correctUser = isset($_POST['user']) &amp;&amp; $_POST['user'] === $user;
  $correctPassword = isset($_POST['password']) &amp;&amp; $_POST['password'] === $password;
  $loginSuccessful = $correctUser &amp;&amp; $correctPassword;
  if ($loginSuccessful) {
    $_SESSION['loggedin'] = true;
    header('Location: index.php');
    die();
  }
}
?>

&lt;!DOCTYPE html>
&lt;html lang="de">

&lt;head>
  &lt;meta charset="UTF-8">
  &lt;meta http-equiv="X-UA-Compatible" content="IE=edge">
  &lt;meta name="viewport" content="width=device-width, initial-scale=1.0">
  &lt;title>Auto-Login Beispiel | VB.NET Cefsharp&lt;/title>
  &lt;style>
    html,
    body {
      padding: 0;
      margin: 0;
      height: 100%;
    }

    body {
      display: flex;
      justify-content: center;
      align-items: center;
    }

    #frmLogin {
      display: flex;
      flex-direction: column;
    }

    input {
      background: white;
      margin-bottom: 0.5em;
    }

    input[type="submit"] {
      cursor: pointer;
    }
  &lt;/style>
&lt;/head>

&lt;body>

  &lt;form id="frmLogin" method="POST" action="">
    &lt;input name="user">
    &lt;input type="password" name="password">
    &lt;input type="submit" name="login" value="Anmelden">

    &lt;?php
    if ($loginAttempted &amp;&amp; !$loginSuccessful) {
      ?>
      &lt;hr>
      &lt;p>Login fehlgeschlagen :(&lt;/p>
      &lt;?php
    }
    ?>
  &lt;/form>

&lt;/body>

&lt;/html></pre>



<h4 class="wp-block-heading">Erklärung zum Login-Skript</h4>



<p>Nun versuche ich einmal relativ kurz und bündig die einzelnen Bestandteile zu erklären. Diese bestehen wie erwähnt aus einem PHP-Teil, einem Styling-Abschnitt und dem mehr oder weniger dynamisch generierten &#8222;Body&#8220;.</p>



<p><strong>Zuerst </strong>müssen wir wie immer wenn wir mit PHP-Sitzungen arbeiten wollen, die &#8222;<strong><a href="https://www.php.net/manual/de/function.session-start.php" target="_blank" rel="noreferrer noopener">session_start</a></strong>&#8222;-Methode verwenden. <strong>Anschließend </strong>haben wir dann den <strong>Zugriff auf </strong>die globale &#8222;<strong>$_SESSION</strong>&#8222;-Variable. Somit können wir beispielsweise den &#8222;ich bin eingeloggt&#8220;-Status speichern und überprüfen.</p>



<p>Der <strong>erste Block </strong>sorgt dafür, dass wir bei entsprechender GET-Anfrage an der Server einen <strong>Logout durchführen</strong>. Somit können wir uns nicht nur ein- sondern auch ausloggen. Den Status darüber geben wir dann an die PHP-Sitzung weiter.</p>



<p><strong>Anschließend </strong>legen wir ein paar <strong>Nutzerdaten </strong>hardcoded fest (beachte den Hinweis oben – bitte nicht in Produktiv-Systemen..). Diese werden dann <strong>überprüft </strong>und bei Erfolg <strong>gespeichert</strong>. Natürlich können wir dann in diesem Schritt auch sofort <strong>zum geschützten Bereich umleiten</strong>.</p>



<p>Um das Ganze jetzt nicht noch in einen CSS-Kurs ausarten zu lassen, würde ich das jetzt erstmal so stehen lassen. Letztendlich sorge ich z. B. dafür, dass das Formular n bissl mittig dargestellt wird. Dann bekommen die Inputs noch eine Hintergrundfarbe und der Button einen anderen Cursor.</p>



<p>Im &#8222;Body&#8220; des HTML-Dokuments bauen wir dann ein relativ <strong>billiges Login-Formular</strong>. <strong>Falls </strong>eine <strong>fehlgeschlagene Anmeldung</strong> stattgefunden hat, <strong>geben </strong>wir hier noch eine entsprechende Information <strong>aus</strong>.</p>



<h4 class="wp-block-heading">Der geschützte Bereich – index.php</h4>



<figure class="wp-block-image size-full"><a href="https://robbelroot.de/wp-content/uploads/2022/03/VB-NET-Webbrowser-eingeloggt-im-geschuetzten-Bereich.png"><img loading="lazy" decoding="async" width="267" height="131" src="https://robbelroot.de/wp-content/uploads/2022/03/VB-NET-Webbrowser-eingeloggt-im-geschuetzten-Bereich.png" alt="VB NET Webbrowser eingeloggt im geschützten Bereich" class="wp-image-9789" title="VB NET Webbrowser eingeloggt im geschützten Bereich"/></a><figcaption>VB NET Webbrowser eingeloggt im geschützten Bereich</figcaption></figure>



<p>Nach dem Login erstellen wir nun den <strong>geschützten Bereich</strong>, Welcher hier erstmal nur eine <strong>simple Meldung </strong>darstellt. Zusätzlich haben wir analog zum Code oben die <strong>Möglichkeit</strong>, einen <strong>Logout durchzuführen</strong>.</p>



<p><strong>Hier </strong>ist das kleinere &#8222;index.php&#8220;-<strong>Skript</strong>:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">&lt;?php
session_start();

$notLoggedIn = !isset($_SESSION['loggedin']);
if ($notLoggedIn) {
  header('Location: login.php');
  die();
}

?>

&lt;!DOCTYPE html>
&lt;html lang="de">
&lt;head>
  &lt;meta charset="UTF-8">
  &lt;meta http-equiv="X-UA-Compatible" content="IE=edge">
  &lt;meta name="viewport" content="width=device-width, initial-scale=1.0">
  &lt;title>Yay, Du bist eingeloggt | VB.NET Cefsharp&lt;/title>
&lt;/head>
&lt;body>
  &lt;h1>Yay eingeloggt..&lt;/h1>
  &lt;a href="login.php?logout">ausloggen..&lt;/a>
&lt;/body>
&lt;/html></pre>



<p>Ähnlich zum oben geschriebenen Code benutzen wir auch hier die &#8222;session_start&#8220;-Methode. Danach können wir mit den Sitzungsdaten prüfen, ob wir eingeloggt sind. Wenn dem nicht so ist, schmeißen wir den jeweiligen Nutzer an dieser Stelle raus und leiten ihn zum Login-Skript um.</p>



<p>Final kommt dann die letztliche minimale Ausgabe im &#8222;Body&#8220;, um etwas sehen zu können.</p>



<h3 class="wp-block-heading">Die Visual Basic Seite des Autologins</h3>



<figure class="wp-block-image size-full"><a href="https://robbelroot.de/wp-content/uploads/2022/03/VB-NET-Webbrowser-Autologin.gif"><img loading="lazy" decoding="async" width="845" height="511" src="https://robbelroot.de/wp-content/uploads/2022/03/VB-NET-Webbrowser-Autologin.gif" alt="VB NET Webbrowser Autologin" class="wp-image-9803" title="VB NET Webbrowser Autologin"/></a><figcaption>VB NET Webbrowser Autologin</figcaption></figure>



<p>Im nächsten Schritt kommen wir zur <strong>VB NET basierten Seite des Autologins</strong>. Wir müssen kurzum dafür sorgen, dass der Browser zuerst unsere <strong>URL öffnet</strong>. Die Umleitung zur jeweiligen Seite passiert ja auch schon mehr oder weniger automatisch. Dennoch nehmen wir die Login-URL als Start-URL.</p>



<p>Ändere den <strong>Form-Load-Ereignishandler</strong> daher so ab:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="visualbasic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">Private Async Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    Await PrepareBrowserAsync()
    Await Wb.LoadUrlAsync("https://robbelroot.de/wbloginbeispiel/login.php")
    Await WaitForElementAsync("#frmLogin")
    ' MessageBox.Show("Die Login-Form ist da!")
    Await AutologinAsync()
End Sub</pre>



<p>Wir sagen hier, dass wir gerne die jeweilige <strong>URL öffnen</strong> möchten. Beachte wie gesagt, dass ich Diese <strong>nach Veröffentlichung </strong>des Beitrags &#8222;<strong>deaktivieren</strong>&#8220; werde. <strong>Danach warten </strong>wir <strong>auf </strong>das HTML-Element mit der Id &#8222;<strong>frmLogin</strong>&#8222;. Zuletzt geben wir dann eine Meldung aus.</p>



<p><strong>Probiere </strong>doch einfach mal aus, im <strong>Login</strong>-Skript <strong>nach </strong>der &#8222;<strong>session_start</strong>&#8222;-Methode ein &#8222;<strong>sleep</strong>(2)&#8220; einzuführen. Damit kannst Du das PHP-Skript 2 Sekunden warten lassen. <strong>Dadurch zeigt </strong>sich die  &#8222;<strong>WaitForElementAsync</strong>&#8222;-Funktion noch einmal in Ihrer <strong>vollen Gänze</strong>.</p>



<p>Danach beschäftigen wir uns mit der automatischen Anmeldung auf einer Webseite via VB NET selbst. Lösche also gerne wieder die &#8222;MessageBox&#8220; von oben heraus und ersetze dies durch z. B. eine &#8222;AutologinAsync()&#8220;-Funktion.</p>



<p>Diese Funktion werden wir natürlich im <strong>nächsten Schritt </strong>erstellen. Ich habe hier übrigens <strong>Warte</strong>&#8211;<strong>Anweisungen </strong>eingeführt, damit wir überhaupt etwas mitbekommen. Diese Anweisungen kannst Du natürlich dann rauswerfen.</p>



<p>Das Skript selbst macht letztendlich nichts Anderes, als die verschiedenen Elemente durch normale <strong>Selektoren anzuwählen</strong>. Danach <strong>setzen </strong>wir die <strong>Werte </strong>der Eingabefelder und <strong>simulieren </strong>zum Schluss einen <strong>Klick </strong>auf den Login-Button.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="visualbasic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">    Private Async Function AutologinAsync() As Task
        ' ONLY FOR THE DEMO!!
        Dim user = "benutzer"
        Dim password = "passwort"
        Await Wb.EvaluateScriptAsync($"document.querySelector('input[name=""user""]').value = '{user}'")
        Await Task.Delay(1000)
        Await Wb.EvaluateScriptAsync($"document.querySelector('input[name=""password""]').value = '{password}'")
        Await Task.Delay(1000)
        Await Wb.EvaluateScriptAsync($"document.querySelector('input[name=""login""]').click()")
    End Function</pre>



<h2 class="wp-block-heading" id="fazit-vb-net-webbrowser-alternative">Fazit &#8211; VB NET Webbrowser Alternative</h2>



<figure class="wp-block-image size-full"><a href="https://robbelroot.de/wp-content/uploads/2022/02/VB-NET-Tutorial-1-Fazit.jpg"><img loading="lazy" decoding="async" width="1200" height="628" src="https://robbelroot.de/wp-content/uploads/2022/02/VB-NET-Tutorial-1-Fazit.jpg" alt="VB NET Webbrowser Alternative" class="wp-image-8236" title="VB NET Webbrowser Alternative"/></a><figcaption>VB NET Webbrowser Alternative</figcaption></figure>



<p><strong>In Vergangenheit </strong>war der <strong>Umgang mit </strong>dem <strong>Webbrowser </strong>Control teilweise ein <strong>Graus</strong>. Aus <strong>verschiedenen Gründen</strong>, hat er unseren Entwickler-Alltag <strong>erschwert</strong>. An sich war der Browser natürlich eine tolle Integrations-Möglichkeit, allerdings mit &#8222;Macken&#8220;.</p>



<p>Dabei spreche ich von diversen<strong> Fehlern</strong>, <strong>Styling</strong>-Probleme und <strong>fehlende </strong>einfache <strong>JavaScript Verwendung</strong>. Diese machen es nicht nur den Nutzern selbst schwer, sondern nerven uns auch als Entwickler ungemein.</p>



<p>Im <strong>heutigen Beitrag </strong>habe ich Dir daher gezeigt, <strong>wie </strong>Du die <strong>moderne Alternative </strong>namens Cefsharp <strong>installieren </strong>kannst. Diese <strong>für NET</strong>&#8211;<strong>Entwickler </strong>erstellte <strong>Chromium</strong>&#8211;<strong>Portierung </strong>bietet uns eine <strong>moderne Alternative </strong>zum alten Webbrowser-Control.</p>



<p><strong>Neben Standard</strong>-Funktionen, wie z. B. das <strong>Aufrufen einer URL</strong>, haben wir uns auch <strong>noch </strong>mit der <strong>Ausführung </strong>von JavaScript beschäftigt. Im <strong>letzten Abschnitt</strong> des Beitrages haben wir uns dann sogar noch eine <strong>automatisierte Anmeldung </strong>angeschaut.</p>



<h2 class="wp-block-heading" id="downloads">Downloads</h2>



<div class="wp-block-buttons is-layout-flex wp-block-buttons-is-layout-flex">
<div class="wp-block-button"><a class="wp-block-button__link" href="https://bit.ly/vbnet-webbrowser-alternative-download" target="_blank" rel="noreferrer noopener">VBWebbrowserAlternative.zip</a></div>
</div>



<h2 class="wp-block-heading" id="weiterfuhrende-links">Weiterführende Links</h2>



<ul class="wp-block-list"><li><a href="https://robbelroot.de/blog/vbnet-webbrowser-control/" target="_blank" rel="noreferrer noopener"><strong>VB NET Webbrowser Beispiel</strong></a></li><li><a href="https://robbelroot.de/blog/vbnet-webbrowser-get-element-by-class/" target="_blank" rel="noreferrer noopener"><strong>Webbrowser Elemente anhand Klasse finden </strong></a></li><li><strong><a href="https://robbelroot.de/blog/vbnet-timer-beispiel-code-im-intervall-ausfuehren/" target="_blank" rel="noreferrer noopener">Timer Beispiel in VB.NET</a></strong></li></ul>
<p>Der Beitrag <a href="https://robbelroot.de/blog/vb-net-webbrowser-alternative/">&#x1f310; VB NET Webbrowser Alternative</a> erschien zuerst auf <a href="https://robbelroot.de">Robert Skibbe</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://robbelroot.de/blog/vb-net-webbrowser-alternative/feed/</wfw:commentRss>
			<slash:comments>18</slash:comments>
		
		
			</item>
		<item>
		<title>VB.NET Webbrowser Get element by Class</title>
		<link>https://robbelroot.de/blog/vbnet-webbrowser-get-element-by-class/</link>
					<comments>https://robbelroot.de/blog/vbnet-webbrowser-get-element-by-class/#comments</comments>
		
		<dc:creator><![CDATA[Robert Skibbe]]></dc:creator>
		<pubDate>Sun, 04 Jul 2021 18:04:36 +0000</pubDate>
				<category><![CDATA[Allgemein]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Visual Basic .NET]]></category>
		<category><![CDATA[Visual Basic .NET Problemlösungen]]></category>
		<category><![CDATA[browser]]></category>
		<category><![CDATA[chrome]]></category>
		<category><![CDATA[class]]></category>
		<category><![CDATA[classname]]></category>
		<category><![CDATA[element]]></category>
		<category><![CDATA[explorer]]></category>
		<category><![CDATA[find]]></category>
		<category><![CDATA[finden]]></category>
		<category><![CDATA[firefox]]></category>
		<category><![CDATA[get]]></category>
		<category><![CDATA[get element by class]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[internet]]></category>
		<category><![CDATA[internet explorer]]></category>
		<category><![CDATA[klasse]]></category>
		<category><![CDATA[name]]></category>
		<category><![CDATA[opera]]></category>
		<category><![CDATA[search]]></category>
		<category><![CDATA[suche]]></category>
		<category><![CDATA[vb.net]]></category>
		<category><![CDATA[vbnet]]></category>
		<category><![CDATA[webbrowser]]></category>
		<category><![CDATA[www]]></category>
		<guid isPermaLink="false">https://robbelroot.de/?p=2987</guid>

					<description><![CDATA[<p>VB.NET Webbrowser Get element by Class Du möchtest im Webbrowser Control an ein gewisses Element anhand der Klasse kommen und der Suchbegriff &#8222;VB.NET Webbrowser Get element by Class&#8220; führte Dich her? Dann bist Du hier richtig, denn in diesem Beitrag zeige ich Dir unter anderem, wie Du mit Hilfe der &#8230;</p>
<p>Der Beitrag <a href="https://robbelroot.de/blog/vbnet-webbrowser-get-element-by-class/">VB.NET Webbrowser Get element by Class</a> erschien zuerst auf <a href="https://robbelroot.de">Robert Skibbe</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-image size-large"><a href="https://robbelroot.de/wp-content/uploads/2021/07/VB.NET-Webbrowser-Get-Element-By-Class.png"><img loading="lazy" decoding="async" width="1024" height="536" src="https://robbelroot.de/wp-content/uploads/2021/07/VB.NET-Webbrowser-Get-Element-By-Class-1024x536.png" alt="VB.NET Webbrowser Get Element By Class" class="wp-image-2988" title="VB.NET Webbrowser Get Element By Class" srcset="https://robbelroot.de/wp-content/uploads/2021/07/VB.NET-Webbrowser-Get-Element-By-Class-1024x536.png 1024w, https://robbelroot.de/wp-content/uploads/2021/07/VB.NET-Webbrowser-Get-Element-By-Class-300x157.png 300w, https://robbelroot.de/wp-content/uploads/2021/07/VB.NET-Webbrowser-Get-Element-By-Class-768x402.png 768w, https://robbelroot.de/wp-content/uploads/2021/07/VB.NET-Webbrowser-Get-Element-By-Class-700x366.png 700w, https://robbelroot.de/wp-content/uploads/2021/07/VB.NET-Webbrowser-Get-Element-By-Class-332x174.png 332w, https://robbelroot.de/wp-content/uploads/2021/07/VB.NET-Webbrowser-Get-Element-By-Class.png 1200w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a><figcaption>VB.NET Webbrowser Get Element By Class</figcaption></figure>






<h2 class="wp-block-heading">VB.NET Webbrowser Get element by Class</h2>



<p>Du <strong>möchtest </strong>im <strong>Webbrowser Control an </strong>ein <strong>gewisses Element anhand </strong>der <strong>Klasse </strong>kommen und der Suchbegriff &#8222;<strong>VB.NET Webbrowser Get element by Class</strong>&#8220; führte Dich her?</p>



<p><strong>Dann </strong>bist Du <strong>hier richtig</strong>, denn in <strong>diesem Beitrag </strong>zeige ich Dir unter anderem, wie Du mit <strong>Hilfe </strong>der <strong>Webbrowser</strong>&#8211;<strong>Control</strong>&#8211;<strong>Methoden </strong>an ein Element mit einem <strong>Klassen</strong>&#8211;<strong>Namen </strong>kommst.</p>



<p><strong>Falls </strong>Du <strong>allerdings auf </strong>der <strong>Suche nach </strong>einem einfachen <a href="https://robbelroot.de/blog/vbnet-webbrowser-control/" target="_blank" rel="noreferrer noopener">VB.NET <strong>Webbrowser</strong>-Control <strong>Beispiel</strong></a><strong> </strong>bist, kannst Du in meinen Beitrag dazu nachlesen.</p>



<p><strong>Noch </strong>einen Schritt <strong>einfacher</strong>, hast Du es <strong>mit </strong>meinem <strong>Beitrag über </strong>das <strong>öffnen </strong>einer <strong>Webseite </strong>in &#8222;<strong><a href="https://robbelroot.de/blog/vbnet-webseite-oeffnen/" target="_blank" rel="noreferrer noopener">VB.NET Webseite öffnen</a></strong>&#8222;.</p>



<h2 class="wp-block-heading">Element anhand Id bekommen</h2>



<p><strong>Wer schonmal </strong>detaillierter <strong>mit </strong>dem <strong>Webbrowser</strong>-Control <strong>gearbeitet </strong>hat, <strong>wird </strong>sicherlich schon <strong>Bekanntschaft mit </strong>der <strong><a href="https://docs.microsoft.com/de-de/dotnet/api/system.windows.forms.htmldocument.getelementbyid?view=net-5.0" target="_blank" rel="noreferrer noopener">getElementById</a></strong>-Funktion der <strong><a href="https://docs.microsoft.com/de-de/dotnet/api/system.windows.forms.webbrowser.document?view=net-5.0" target="_blank" rel="noreferrer noopener">Document</a></strong>-Eigenschaft gemacht haben.</p>



<p>Die <strong>getElementById</strong>&#8211;<strong>Funktion </strong>wird <strong>ähnlich </strong>der von uns hier <strong>benötigten Funktion </strong>aufgerufen und <strong>gehört zu </strong>den <strong>essentiellen </strong>Webbrowser-<strong>Hilfsmitteln</strong>, daher <strong>zeige </strong>ich Sie <strong>hier noch einmal</strong>.  </p>



<p><strong>Um </strong>mit dessen Hilfe <strong>an </strong>ein <strong>Element </strong>via Id zu kommen, <strong>sieht </strong>ein <strong>Aufruf </strong>zum Beispiel <strong>wie folgt aus</strong>:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="visualbasic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">Dim theElement = wb.getElementById("&lt;theId>")</pre>



<h2 class="wp-block-heading" id="script-errors-suppressed">Fehler unterbinden</h2>



<h3 class="wp-block-heading">Fehler vermeiden – VB.NET Webbrowser Get element by Class</h3>



<p>Um ggf. <strong>besser mit </strong>dem <strong>Webbrowser arbeiten </strong>zu können, empfiehlt es sich <strong>eventuell</strong>, die <strong><a href="https://docs.microsoft.com/de-de/dotnet/api/system.windows.forms.webbrowser.scripterrorssuppressed?view=net-5.0" target="_blank" rel="noreferrer noopener">ScriptErrorsSuppressed</a></strong>-Eigenschaft auf True zu stellen.</p>



<p>Damit werden <strong>wie </strong>der <strong>Name schon sagt</strong>, <strong>diverse Skriptfehler unterdrückt </strong>und gewähren somit einen <strong>flüssigeren</strong>, bzw. besseren <strong>Ablauf</strong>.</p>



<p><strong>Wer </strong>sich ggf. bei der Arbeit <strong>gewisse Abläufe</strong>, oder <strong>Fehler nicht erklären </strong>kann, <strong>sollte </strong>die <strong>Eigenschaft </strong>auch <strong>testweise </strong>wieder <strong>deaktivieren</strong>, um zu schauen, ob es <strong>eventuell </strong>einen <strong>relevanten Fehler </strong>gibt. </p>



<h2 class="wp-block-heading" id="get-elements-by-class-erweiterung">GetElementsByClass – eigene Erweiterungen</h2>



<p>Hier stelle ich <strong>zwei Erweiterungsmethoden</strong> für das WebBrowser-Document vor, um leichter an <strong>Elemente via Klassennamen</strong> zu kommen.</p>



<h3 class="wp-block-heading">GetElementByClass</h3>



<p>Die <strong>erste </strong>der beiden <strong>Funktionen greift </strong>auf die <strong>zweite Funktion </strong>zu, <strong>um </strong>dessen <strong>erstes Ergebnis oder Nothing </strong>zu liefern.</p>



<p>Sie <strong>liefert </strong>also <strong>entweder </strong>das erste <strong>Element </strong>mit diesem Klassennamen, <strong>oder </strong>eben <strong>Nothing</strong>, wenn nichts gefunden wurde.</p>



<h3 class="wp-block-heading">GetElementsByClass</h3>



<p>Diese <strong>Funktion iteriert </strong>alle Html-<strong>Elemente des Dokuments </strong>und <strong>ruft </strong>das <strong>className</strong>-Attribut des Elements <strong>ab</strong>.</p>



<p><strong>Vorher </strong>gehe ich noch hin und <strong>kille </strong>den <strong>führenden Punkt</strong>, <strong>falls </strong>einer beim Aufruf der Funktion – wie bei Klassennamen üblich – <strong>übergeben </strong>wurde.</p>



<p><strong>Leider heißt </strong>das <strong>so</strong>, obwohl man aus dem Web halt an das Attribut &#8222;class&#8220; gewöhnt ist.</p>



<p><strong>Nachdem </strong>wir die <strong>Klassennamen</strong> als <strong>String </strong>noch mit <strong>Trim </strong>von <strong>führenden </strong>und <strong>nachstehenden </strong>Leerzeichen gesäubert haben, können wir die <strong>Klassen </strong>durch <strong>Split </strong>in eine <strong>Auflistung packen</strong>.</p>



<p><strong>Wenn </strong>diese <strong>Auflistung </strong>dann unsere <strong>übergebene Klasse beinhaltet</strong>, dann <strong>handelt </strong>es sich bei dem Element um ein <strong>Element </strong>unserer <strong>Begierde </strong>und wird letztendlich der <strong>elements</strong>-Variable <strong>für </strong>die <strong>Rückgabe hinzugefügt</strong>.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="visualbasic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">Imports System.Runtime.CompilerServices

Module modBrowserExtensions

    &lt;Extension>
    Public Function GetElementByClass(doc As HtmlDocument, cls As String) As HtmlElement
        Dim elements = GetElementsByClass(doc, cls)
        Return elements.FirstOrDefault()
    End Function

    &lt;Extension>
    Public Function GetElementsByClass(doc As HtmlDocument, cls As String) As List(Of HtmlElement)
        If cls.StartsWith(".") Then
            cls = cls.Substring(1)
        End If
        Dim elements = New List(Of HtmlElement)
        For Each element As HtmlElement In doc.All
            Dim className = element.GetAttribute("className").Trim()
            Dim classNames = className.Split(" ")
            If classNames.Contains(cls) Then
                elements.Add(element)
            End If
        Next
        Return elements
    End Function

End Module
</pre>



<h2 class="wp-block-heading">Code – VB.NET Webbrowser Get element by Class</h2>



<p>So <strong>nun </strong>kommen wir <strong>zum Code </strong>des heutigen Beitrages, wo wir schauen, wie man an ein Element im Webbrowser-Document mit Hilfe des Klassennamen kommen kann (VB.NET Webbrowser Get element by Class).</p>



<h3 class="wp-block-heading">Vorbereitung</h3>



<h4 class="wp-block-heading">Styling</h4>



<p>Auch <strong>in diesem Beitrag </strong>werde ich dem <strong>Webbrowser </strong>den <strong>Namen </strong>&#8222;<strong>wb</strong>&#8220; geben, da es <strong>schließlich </strong>unser <strong>einziges Webbrowser</strong>-Control sein wird.</p>



<p><strong>Ansonsten </strong>sollten wir natürlich immer auf einen <strong>prägnanten Namen </strong>für Controls achten!</p>



<p><strong>Als nächstes </strong>habe ich die <strong><a href="https://docs.microsoft.com/de-de/dotnet/api/system.windows.forms.control.dock?view=net-5.0" target="_blank" rel="noreferrer noopener">Dock-Eigenschaft</a> auf None </strong>gestellt, damit der <strong>Webbrowser nicht </strong>den <strong>gesamten Platz </strong>einnimmt und wir <strong>noch Platz für </strong>eventuelle <strong>andere Steuerelemente </strong>haben.</p>



<p><strong>Wie </strong><a href="#script-errors-suppressed">oben</a> <strong>vorgestellt</strong>, stelle ich <strong>auch </strong>die <strong>ScriptErrorsSuppressed</strong>-Eigenschaft auf <strong>True</strong>.</p>



<p>Die <strong>Form</strong>, bzw. dessen <strong>Startposition </strong>habe ich <strong>wie </strong>fast <strong>immer </strong>auf &#8222;<strong>CenterScreen</strong>&#8220; gestellt, da es besonders auf großen Bildschirmen nervig ist (bei mir 50&#8243; Curved..), wenn das Fenster jedes Mal oben links in der letzten Ecke hängt..</p>



<h4 class="wp-block-heading">Controls</h4>



<h5 class="wp-block-heading">TextBox – tbUrl</h5>



<p><strong>Mit </strong>dieser <strong>TextBox </strong>kannst Du eine <strong>URL eingeben und </strong>anschließend dorthin <strong>navigieren</strong>.</p>



<p>Ich <strong>wollte </strong>die <strong>URL nicht hardcoden</strong>, <strong>da </strong>sich die <strong>Ziel-Seite</strong> nach Erstellung meines Beitrages ggf. <strong>ändert und </strong>deshalb <strong>nicht mehr funktioniert</strong>.</p>



<h5 class="wp-block-heading">Button – btnGo</h5>



<p>Mit diesem <strong>Button </strong>kann <strong>zur </strong>angegebenen <strong>URL navigiert </strong>werden.</p>



<h5 class="wp-block-heading">WebBrowser – wb</h5>



<p>Der <strong>Browser mit dem </strong>wir alles in diesem Beitrag <strong>ausprobieren</strong>.</p>



<h5 class="wp-block-heading">TextBox – tbClassName</h5>



<p>In dieser <strong>TextBox </strong>kannst Du einen <strong>Klassennamen </strong>(mit oder ohne Punkt) eingeben und somit nach dem jeweiligen <strong>Element suchen</strong>.</p>



<p>Anschließend wird dessen &#8222;<a href="https://docs.microsoft.com/de-de/dotnet/api/system.windows.forms.htmlelement.innertext?view=net-5.0" target="_blank" rel="noreferrer noopener">InnerText</a>&#8220; <strong>abgegriffen </strong>und in der dafür vorgesehenen TextBox angezeigt.</p>



<h5 class="wp-block-heading">Button – btnGetElementsInnerText</h5>



<p>Mit diesem <strong>Button </strong>wird die <strong>Suche </strong>nach dem <strong>Element </strong>via <strong>Klassenname ausgelöst </strong>und dessen InnerText in die rechte TextBox ausgegeben.</p>



<h5 class="wp-block-heading">TextBox – tbInnerText</h5>



<p>Hier wird der ausgelesene <strong>InnerText des Html-Elements ausgegeben</strong> und angezeigt.</p>



<p>Die TextBox ist <strong>bewusst auf ReadOnly</strong> gestellt, damit man dort nicht rumpfuschen kann.</p>



<h3 class="wp-block-heading">Zur URL navigieren</h3>



<h4 class="wp-block-heading">Via Button</h4>



<p>Mit diesem Button <strong>navigieren </strong>wir <strong>zur Ziel-Seite</strong>, nachdem wir vorher die <strong>URL aus </strong>der <strong>TextBox mit </strong>der <strong><a href="https://docs.microsoft.com/de-de/dotnet/api/system.string.trim?view=net-5.0" target="_blank" rel="noreferrer noopener">Trim-Funktion</a></strong> abgegriffen haben.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="visualbasic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">Private Sub btnGo_Click(sender As Object, e As EventArgs) Handles btnGo.Click
    Dim url = tbUrl.Text.Trim()
    wb.Navigate(url)
End Sub</pre>



<h4 class="wp-block-heading">Via Enter</h4>



<p>Um <strong>via Enter zur</strong> jeweiligen <strong>Seite </strong>zu <strong>navigieren</strong>, fügen wir folgenden Code ein:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="visualbasic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">Private Sub tbUrl_KeyDown(sender As Object, e As KeyEventArgs) Handles tbUrl.KeyDown
    If e.KeyCode = Keys.Enter Then
        Dim url = tbUrl.Text.Trim()
        wb.Navigate(url)
    End If
End Sub</pre>



<p><strong>Könnte man </strong>natürlich <strong>durch </strong>eine zentrale <strong>Sub lösen</strong>, um <strong>duplicated Code </strong>zu <strong>vermeiden</strong>..</p>



<h3 class="wp-block-heading">Den InnerText auslesen</h3>



<p><strong>Um </strong>nun den <strong>InnerText auszulesen</strong>, müssen wir zuerst <strong>an </strong>das <strong>jeweilige Element </strong>mit Hilfe des <strong>Klassennamens </strong>kommen.</p>



<p><strong>Leider </strong>fängt hier das <strong>große Fragezeichen </strong>an, <strong>denn </strong>das <strong>WebBrowser</strong>-Control <strong>hat </strong>dämlicherweise <strong>keine </strong>native <strong>Funktion um </strong>ein <strong>Element </strong>anhand seines <strong>Klassennamens </strong>zu <strong>bekommen</strong>.</p>



<p>Zum <strong>Glück </strong>haben wir aber dafür <strong><a href="#get-elements-by-class-erweiterung">weiter oben</a></strong> unsere <strong>eigene </strong>Extension-<strong>Methoden </strong>gebaut!</p>



<pre class="EnlighterJSRAW" data-enlighter-language="visualbasic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">Private Sub btnGetElementsInnerText_Click(sender As Object, e As EventArgs) Handles btnGetElementsInnerText.Click
    Dim className = tbClassName.Text.Trim()
    Dim element = wb.Document.GetElementByClass(className)
    If element IsNot Nothing Then
        tbInnerText.Text = element.InnerText
    End If
End Sub</pre>



<h2 class="wp-block-heading">Kompletter Code – VB.NET Webbrowser Get element by Class</h2>



<p><strong>Hier </strong>findest Du wie fast bei allen meiner Beiträge den <strong>kompletten Beispielcode</strong>, achte nur darauf, dass Dieser je nach Webseite <strong>eventuell nicht funktioniert </strong>(was nicht am Code direkt liegt!).</p>



<p>Dabei solltest Du auf die <strong>korrekten Klassennamen </strong>achten und überprüfen, ob der <strong>Klassenname </strong>sich <strong>nicht </strong>etwa <strong>bei jedem Aufruf </strong>der Seite <strong>ändert</strong>.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="visualbasic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">Public Class Form1

    Private Sub btnGo_Click(sender As Object, e As EventArgs) Handles btnGo.Click
        Dim url = tbUrl.Text.Trim()
        wb.Navigate(url)
    End Sub

    Private Sub tbUrl_KeyDown(sender As Object, e As KeyEventArgs) Handles tbUrl.KeyDown
        If e.KeyCode = Keys.Enter Then
            Dim url = tbUrl.Text.Trim()
            wb.Navigate(url)
        End If
    End Sub

    Private Sub btnGetElementsInnerText_Click(sender As Object, e As EventArgs) Handles btnGetElementsInnerText.Click
        Dim className = tbClassName.Text.Trim()
        Dim element = wb.Document.GetElementByClass(className)
        If element IsNot Nothing Then
            tbInnerText.Text = element.InnerText
        End If
    End Sub

End Class

Imports System.Runtime.CompilerServices

Module modBrowserExtensions

    &lt;Extension>
    Public Function GetElementByClass(doc As HtmlDocument, cls As String) As HtmlElement
        Dim elements = GetElementsByClass(doc, cls)
        Return elements.FirstOrDefault()
    End Function

    &lt;Extension>
    Public Function GetElementsByClass(doc As HtmlDocument, cls As String) As List(Of HtmlElement)
        If cls.StartsWith(".") Then
            cls = cls.Substring(1)
        End If
        Dim elements = New List(Of HtmlElement)
        For Each element As HtmlElement In doc.All
            Dim className = element.GetAttribute("className").Trim()
            Dim classNames = className.Split(" ")
            If classNames.Contains(cls) Then
                elements.Add(element)
            End If
        Next
        Return elements
    End Function

End Module</pre>



<h2 class="wp-block-heading">Downloads</h2>



<div class="wp-block-buttons is-layout-flex wp-block-buttons-is-layout-flex">
<div class="wp-block-button"><a class="wp-block-button__link" href="/downloads/vbnet/WebbrowserGetElementByClassExample.zip" target="_blank" rel="noreferrer noopener">WebbrowserGetElementByClassExample.zip</a></div>
</div>
<p>Der Beitrag <a href="https://robbelroot.de/blog/vbnet-webbrowser-get-element-by-class/">VB.NET Webbrowser Get element by Class</a> erschien zuerst auf <a href="https://robbelroot.de">Robert Skibbe</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://robbelroot.de/blog/vbnet-webbrowser-get-element-by-class/feed/</wfw:commentRss>
			<slash:comments>3</slash:comments>
		
		
			</item>
		<item>
		<title>VB.NET Webbrowser Control</title>
		<link>https://robbelroot.de/blog/vbnet-webbrowser-control/</link>
					<comments>https://robbelroot.de/blog/vbnet-webbrowser-control/#comments</comments>
		
		<dc:creator><![CDATA[Robert Skibbe]]></dc:creator>
		<pubDate>Sun, 04 Jul 2021 14:07:54 +0000</pubDate>
				<category><![CDATA[Allgemein]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Visual Basic .NET]]></category>
		<category><![CDATA[Visual Basic .NET lernen]]></category>
		<category><![CDATA[browse]]></category>
		<category><![CDATA[browser]]></category>
		<category><![CDATA[chrome]]></category>
		<category><![CDATA[control]]></category>
		<category><![CDATA[edge]]></category>
		<category><![CDATA[firefox]]></category>
		<category><![CDATA[http]]></category>
		<category><![CDATA[https]]></category>
		<category><![CDATA[internet]]></category>
		<category><![CDATA[internet explorer]]></category>
		<category><![CDATA[navigate]]></category>
		<category><![CDATA[navigieren]]></category>
		<category><![CDATA[net]]></category>
		<category><![CDATA[opera]]></category>
		<category><![CDATA[steuerelement]]></category>
		<category><![CDATA[url]]></category>
		<category><![CDATA[vb.net]]></category>
		<category><![CDATA[vbnet]]></category>
		<category><![CDATA[webbrowser]]></category>
		<category><![CDATA[www]]></category>
		<guid isPermaLink="false">https://robbelroot.de/?p=2935</guid>

					<description><![CDATA[<p>VB.NET Webbrowser Control In diesem Beitrag zeige ich Dir wichtige Eigenschaften und Funktionalitäten des VB.NET Webbrowser Control. Von Zeit zu Zeit könnte es vorkommen, dass Du in deinem Programm auch mal einen Webbrowser darstellen und ggf. im Detail damit arbeiten musst. Diese Arbeit kann unter anderem sein, dass Du den &#8230;</p>
<p>Der Beitrag <a href="https://robbelroot.de/blog/vbnet-webbrowser-control/">VB.NET Webbrowser Control</a> erschien zuerst auf <a href="https://robbelroot.de">Robert Skibbe</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-image size-large"><a href="https://robbelroot.de/wp-content/uploads/2021/07/VB.NET-Webbrowser-Control.png"><img loading="lazy" decoding="async" width="1024" height="536" src="https://robbelroot.de/wp-content/uploads/2021/07/VB.NET-Webbrowser-Control-1024x536.png" alt="VB.NET Webbrowser Control" class="wp-image-2937" title="VB.NET Webbrowser Control" srcset="https://robbelroot.de/wp-content/uploads/2021/07/VB.NET-Webbrowser-Control-1024x536.png 1024w, https://robbelroot.de/wp-content/uploads/2021/07/VB.NET-Webbrowser-Control-300x157.png 300w, https://robbelroot.de/wp-content/uploads/2021/07/VB.NET-Webbrowser-Control-768x402.png 768w, https://robbelroot.de/wp-content/uploads/2021/07/VB.NET-Webbrowser-Control-700x366.png 700w, https://robbelroot.de/wp-content/uploads/2021/07/VB.NET-Webbrowser-Control-332x174.png 332w, https://robbelroot.de/wp-content/uploads/2021/07/VB.NET-Webbrowser-Control.png 1200w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a><figcaption>VB.NET Webbrowser Control</figcaption></figure>






<h2 class="wp-block-heading" id="vb-net-webbrowser-control">VB.NET Webbrowser Control</h2>



<p>In <strong>diesem Beitrag </strong>zeige ich Dir <strong>wichtige Eigenschaften </strong>und <strong>Funktionalitäten </strong>des <strong>VB.NET Webbrowser Control</strong>.</p>



<p>Von Zeit zu Zeit <strong>könnte </strong>es <strong>vorkommen</strong>, <strong>dass </strong>Du <strong>in </strong>deinem <strong>Programm </strong>auch mal <strong>einen Webbrowser </strong>darstellen und ggf. <strong>im Detail </strong>damit<strong> arbeiten </strong>musst.</p>



<p>Diese <strong>Arbeit kann </strong>unter anderem <strong>sein</strong>, <strong>dass </strong>Du den <strong>Quelltext </strong>einer Seite <strong>auslesen oder </strong>die <strong>Oberfläche automatisieren </strong>möchtest, das zeige ich auch im Beitrag &#8222;<strong><a href="https://robbelroot.de/blog/vbnet-webbrowser-get-element-by-class/" target="_blank" rel="noreferrer noopener">VB.NET Get Element By Class</a></strong>&#8222;.</p>



<p><strong>Falls </strong>Du z. B. <strong>nur </strong>eine <strong>Webseite </strong>ohne eigenes Steuerelement <strong>öffnen </strong>möchtest, wirst Du in meinem <strong><a href="/blog/vbnet-webseite-oeffnen" target="_blank" rel="noreferrer noopener">VB.NET Webseite öffnen Beitrag fündig</a></strong>.</p>



<h2 class="wp-block-heading" id="code">Code</h2>



<p><strong>Um mit </strong>dem <strong>VB.NET Webbrowser Control</strong> <strong>zu starten</strong>, <strong>ziehen </strong>wir es einfach <strong>aus </strong>der <strong>Toolbox</strong> auf die Form und starten durch &#x1f913;.</p>



<p>In meinem ersten Beispiel stelle ich die <strong><a href="https://docs.microsoft.com/de-de/dotnet/api/system.windows.forms.control.dock?view=net-5.0" target="_blank" rel="noreferrer noopener">Dock-Eigenschaft</a></strong> des <strong><a href="https://docs.microsoft.com/de-de/dotnet/api/system.windows.forms.webbrowser?view=net-5.0" target="_blank" rel="noreferrer noopener">Webbrowsers</a></strong> <strong>auf None</strong>, <strong>damit </strong>Dieser <strong>nicht </strong>die komplette <strong>Form einnimmt </strong>und ich noch <strong>für Buttons Platz </strong>habe.</p>



<p>Ebenso <strong>stelle ich </strong>die Eigenschaft <strong><a href="https://docs.microsoft.com/de-de/dotnet/api/system.windows.forms.webbrowser.scripterrorssuppressed?view=net-5.0" target="_blank" rel="noreferrer noopener">ScriptErrorsSuppressed</a></strong> <strong>auf True</strong>, ansonsten <strong>bekommt man </strong>so gut wie auf jeder Seite <strong>hunderte Errors </strong>an den Kopf geschmissen.</p>



<p><strong>Zu </strong>guter <strong>Letzt </strong>stelle ich den <strong>Namen </strong>des <strong>Webbrowsers auf </strong>&#8222;<strong>wb</strong>&#8222;, um nicht jedes Mal &#8222;<strong>Webbrowser1</strong>&#8220; <strong>schreiben </strong>zu <strong>müssen</strong>.</p>



<p><strong>Da </strong>es der <strong>einzige Webbrowser </strong>der Anwendung sein wird, sehe ich hier auch <strong>keinen Grund </strong>es – wie sonst immer – <strong>passend </strong>zu <strong>benennen</strong>, denn: &#8222;Was ist hier passend!?&#8220;.</p>



<h3 class="wp-block-heading" id="seite-offnen">Seite öffnen</h3>



<p><strong>Um </strong>mit dem <strong>VB.NET Webbrowser Control</strong> gezielt, also via URL zu <strong>navigieren</strong>, bzw. Ihn mehr oder weniger navigieren zu lassen, <strong>können </strong>wir dessen <strong><a href="https://docs.microsoft.com/de-de/dotnet/api/system.windows.forms.webbrowser.navigate?view=net-5.0" target="_blank" rel="noreferrer noopener">Navigate-Methode</a></strong> <strong>verwenden</strong>.</p>



<p><strong>Dafür </strong>nehme ich das <strong>Beispiel </strong>aus dem Sample-Code, wo wir <strong>analog zu </strong>den gängigen <strong>Browsern aus </strong>einer <strong>Textbox </strong>heraus <strong>navigieren</strong>:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="visualbasic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">Private Sub btnGo_Click(sender As Object, e As EventArgs) Handles btnGo.Click
    wb.Navigate("https://google.de")
End Sub</pre>



<h3 class="wp-block-heading" id="seite-bei-start-laden-vb-net-webbrowser-control">Seite bei Start laden – VB.NET Webbrowser Control</h3>



<p>Wir können <strong>neben </strong>dem <strong>manuellen Navigieren auch </strong>schon <strong>bei Start </strong>der Form eine URL <strong>laden </strong>lassen.</p>



<p>Um den <strong>Browser </strong>schon <strong>bei Start </strong>eine <strong>Url laden </strong>zu lassen, setzen wir einfach <strong>im Designer </strong>die <strong><a href="https://docs.microsoft.com/de-de/dotnet/api/system.windows.forms.webbrowser.url?view=net-5.0" target="_blank" rel="noreferrer noopener">Url-Eigenschaft</a></strong></p>



<h3 class="wp-block-heading" id="aktualisieren">Aktualisieren</h3>



<p><strong>Ähnlich wie </strong>in bekannten <strong>Webbrowsern</strong>, haben wir <strong>auch hier </strong>die Möglichkeit den <strong>Browser</strong>, bzw. dessen Seite mit Hilfe der <strong><a href="https://docs.microsoft.com/de-de/dotnet/api/system.windows.forms.webbrowser.refresh?view=net-5.0" target="_blank" rel="noreferrer noopener">Refresh-Methode</a></strong> <strong>zu aktualisieren</strong>.</p>



<p>In unserem Beispiel <strong>platziere </strong>ich den Aktualisierungs-<strong>Button </strong>– wie gängig – oben:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="visualbasic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">Private Sub btnRefresh_Click(sender As Object, e As EventArgs) Handles btnRefresh.Click
    wb.Refresh()
End Sub</pre>



<h3 class="wp-block-heading" id="vorwarts-navigieren">Vorwärts navigieren</h3>



<p>Der Webbrowser kann durch den Aufruf der <strong><a href="https://docs.microsoft.com/de-de/dotnet/api/system.windows.forms.webbrowser.goforward?view=net-5.0" target="_blank" rel="noreferrer noopener">&#8222;GoForward&#8220;-Methode</a></strong> vorwärts navigieren, aber um es sauber zu machen, müssen wir auch auf die passende Eigenschaft namens &#8222;<strong><a href="https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.webbrowser.cangoforward?view=net-5.0" target="_blank" rel="noreferrer noopener">CanGoForward</a></strong>&#8220; achten.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="visualbasic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">Private Sub btnForward_Click(sender As Object, e As EventArgs) Handles btnForward.Click
    If wb.CanGoForward Then
        wb.GoForward()
    End If
End Sub</pre>



<h3 class="wp-block-heading" id="ruckwarts-navigieren">Rückwärts navigieren</h3>



<p><strong>Ähnlich wie </strong>beim navigieren <strong>nach vorn</strong>, verfahren wir auch hier, wir <strong>prüfen </strong>die <strong><a href="https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.webbrowser.cangoback?view=net-5.0" target="_blank" rel="noreferrer noopener">&#8222;CanGoBack&#8220;-Eigenschaft</a></strong> und <strong>navigieren </strong>entsprechend.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="visualbasic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">Private Sub btnBack_Click(sender As Object, e As EventArgs) Handles btnBack.Click
    If wb.CanGoBack Then
        wb.GoBack()
    End If
End Sub</pre>



<h3 class="wp-block-heading" id="scrollbalken-scrollbarsenabled">Scrollbalken – ScrollBarsEnabled</h3>



<p>Man kann in dem <strong>Webbrowser</strong>-Control auch die <strong>Scrollbalken kontrollieren </strong>indem man dafür die <strong>vorgesehene Eigenschaft </strong>namens &#8222;<strong>ScrollBarsEnabled</strong>&#8220; entsprechend auf <strong>True</strong>, <strong>oder False </strong>stellt.</p>



<h3 class="wp-block-heading" id="kontextmenu-iswebbrowsercontextmenuenabled">Kontextmenü – IsWebBrowserContextMenuEnabled</h3>



<p>Da <strong>Webbrowser </strong>für <strong>gewöhnlich </strong>ein <strong>eigenes Kontextmenü </strong>haben, hat sich das .NET-Team <strong>auch hier </strong>für eine <strong>Konfigurationsmöglichkeit </strong>entschieden</p>



<p>Es <strong>handelt sich um </strong>die <strong>IsWebBrowserContextMenuEnabled</strong>-Eigenschaft, mit dessen Hilfe wir – wie der Name schon erraten lässt – das <strong>native Kontextmenü </strong>des Browsers <strong>aktivieren</strong>, oder <strong>deaktivieren </strong>können.</p>



<h3 class="wp-block-heading" id="seite-fixieren-allownavigation">Seite fixieren – AllowNavigation</h3>



<p>In <strong>gewissen Anwendungsfällen </strong>kann es vorkommen, dass man nach dem <strong>initialen Aufruf </strong>einer Webseite <strong>nicht </strong>möchte, dass zu einer <strong>anderen Seite navigiert </strong>werden kann.</p>



<p>Mit der <strong>AllowNavigation</strong>&#8211;<strong>Eigenschaft </strong>können wir <strong>vermeiden</strong>, dass <strong>andere Webseiten aufgerufen </strong>werden.</p>



<h3 class="wp-block-heading" id="tastenkombinationen-webbrowsershortcutsenabled">Tastenkombinationen – WebBrowserShortcutsEnabled</h3>



<p>Die <strong><a href="https://docs.microsoft.com/de-de/dotnet/api/system.windows.forms.webbrowser.webbrowsershortcutsenabled?view=net-5.0" target="_blank" rel="noreferrer noopener">WebBrowserShortcutsEnabled-Eigenschaft</a></strong> legt fest, ob im Browser die <strong>Tastenkombinationen</strong>, bzw. die Tastenkürzel <strong>aktiviert</strong>, oder <strong>deaktiviert </strong>sind.</p>



<h2 class="wp-block-heading" id="style-engine">Style &amp; Engine</h2>



<h3 class="wp-block-heading" id="moderneres-vb-net-webbrowser-control">Moderneres VB.NET Webbrowser Control</h3>



<p><strong>Nach </strong>einiger <strong>Zeit </strong>die Du <strong>mit </strong>dem <strong>Webbrowser </strong>verbracht hast, wirst Du Dich vermutlich <strong>fragen</strong>, <strong>ob</strong> es nicht <strong>auch </strong>eine <strong>schönere </strong>und <strong>modernere Variante </strong>für das Steuerelement gibt.</p>



<p>Zum Glück <strong>kann </strong>ich <strong>dich beruhigen</strong>, ja diese neuere und <strong>tollere Variante </strong>gibt es!</p>



<p>So können wir einerseits die <strong>Verarbeitung </strong>von <strong>Stylesheets verbessern</strong>, die <strong>Fehler </strong>die im alten Control häufiger auftreten <strong>reduzieren </strong>und vor allem <strong>Performance </strong>und <strong>Support optimieren</strong>.</p>



<p><strong>Wie </strong>man ein <strong>alternatives Webbrowser</strong>-Control verwendet zeige ich Dir <strong>in </strong>einem <strong><a href="https://robbelroot.de/blog/vb-net-webbrowser-alternative/" target="_blank" rel="noreferrer noopener">anderen Beitrag</a></strong>.</p>



<h2 class="wp-block-heading" id="dokument-vb-net-webbrowser-control">Dokument – VB.NET Webbrowser Control</h2>



<p><strong>Wer </strong>ein wenig <strong>Erfahrung </strong>mit <strong>JavaScript </strong>hat wird sich eventuell <strong>fragen</strong>, <strong>ob </strong>man auch in VB.NET an das <strong>Document </strong>des Webbrowsers rankommen kann, kurze Antwort: &#8222;<strong>Ja</strong>, kann man!&#8220;.</p>



<p><strong>Um </strong>an das <strong>Document </strong>des Browsers zu kommen, muss man <strong>einfach nur </strong>die <strong>Document</strong>-Eigenschaft des <strong>Browsers </strong>verwenden und kann dann einige <strong>gewohnte Funktionen </strong>wie <strong>getElementById</strong>() aus <strong>JavaScript </strong>verwenden.</p>



<p><strong>Diese Funktionen </strong>sind <strong>insbesondere </strong>für die <strong>Automation </strong>des VB.NET Webbrowser Controls von <strong>Vorteil </strong>und können Dir so auf verschiedene Arten und Weisen einen Vorteil verschaffen <strong>z. B.</strong> <strong>für </strong>einen <strong>Login </strong>o. Ä.</p>



<h2 class="wp-block-heading" id="kompletter-code-vb-net-webbrowser-control">Kompletter Code – VB.NET Webbrowser Control</h2>



<pre class="EnlighterJSRAW" data-enlighter-language="visualbasic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">Public Class Form1

    Private Sub btnRefresh_Click(sender As Object, e As EventArgs) Handles btnRefresh.Click
        wb.Refresh()
    End Sub

    Private Sub btnGo_Click(sender As Object, e As EventArgs) Handles btnGo.Click
        wb.Navigate(tbUrl.Text)
    End Sub

    Private Sub btnBack_Click(sender As Object, e As EventArgs) Handles btnBack.Click
        If wb.CanGoBack Then
            wb.GoBack()
        End If
    End Sub

    Private Sub btnForward_Click(sender As Object, e As EventArgs) Handles btnForward.Click
        If wb.CanGoForward Then
            wb.GoForward()
        End If
    End Sub

    Private Sub tbUrl_KeyDown(sender As Object, e As KeyEventArgs) Handles tbUrl.KeyDown
        If e.KeyCode = Keys.Enter Then
            wb.Navigate(tbUrl.Text)
        End If
    End Sub

End Class</pre>



<h2 class="wp-block-heading" id="downloads">Downloads</h2>



<div class="wp-block-buttons is-layout-flex wp-block-buttons-is-layout-flex">
<div class="wp-block-button"><a class="wp-block-button__link" href="/downloads/vbnet/WebbrowserControlExample.zip" target="_blank" rel="noreferrer noopener">WebbrowserControlExample.zip</a></div>
</div>



<p></p>
<p>Der Beitrag <a href="https://robbelroot.de/blog/vbnet-webbrowser-control/">VB.NET Webbrowser Control</a> erschien zuerst auf <a href="https://robbelroot.de">Robert Skibbe</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://robbelroot.de/blog/vbnet-webbrowser-control/feed/</wfw:commentRss>
			<slash:comments>3</slash:comments>
		
		
			</item>
	</channel>
</rss>
