VB.NET How to get text from an HTML table? - vb.net

I'm trying to access certain tables and values from a certain html page inside of a webbrowser control. Here's what i'm trying to access:
https://gyazo.com/c4312f860397d0f86ccce425d1fb3d48
In the end, I'm trying to access the value="100" inside of the input name="Server[players]". Is there any way to do this? I'm not using any external addons for visual studio or anything. I've already gotten this working:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim divs = WebBrowser1.Document.GetElementsByTagName("div")
For Each div As HtmlElement In divs
If div.GetAttribute("id") = ("statusdetail-ajax") Then
Dim status As String = div.InnerText
Label1.Text = status
End If
Next
Which just shows me the online/offline status. Any help is greatly appreciated!

You want the GetAttribute() method, like so:
Private Sub DisplayMetaDescription()
If (WebBrowser1.Document IsNot Nothing) Then
Dim Elems As HtmlElementCollection
Dim WebOC as WebBrowser = WebBrowser1
Elems = WebOC.Document.GetElementsByTagName("META")
For Each elem As HtmlElement In Elems
Dim NameStr As String = elem.GetAttribute("name")
If ((NameStr IsNot Nothing) And (NameStr.Length <> 0)) Then
If NameStr.ToLower().Equals("description") Then
Dim ContentStr As String = elem.GetAttribute("content")
MessageBox.Show("Document: " & WebOC.Url.ToString() & vbCrLf & "Description: " & ContentStr)
End If
End If
Next
End If
End Sub
Taken from:
https://msdn.microsoft.com/en-us/library/system.windows.forms.htmlelement.getattribute(v=vs.110).aspx
EDIT:
Here's the same concept adapted to your code:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim inputs = WebBrowser1.Document.GetElementsByTagName("input")
For Each input As HtmlElement In inputs
If input.GetAttribute("id") = ("Server_players") Then
Dim status As String = input.GetAttribute("value")
Label1.Text = status
End If
Next
End Sub
In other words, InnerText returns everything between elements, while GetAttribute() returns an attribute inside an element.
<element attribute="Value">Inner Text</element>

Related

Loop through each item in Listbox and load a webpage

I'm trying to load a new webpage through the control webview2 in .net6+ windows forms, and I'm using a listbox to extract any single item and add it to the url to load on webview.
For example in listbox I have:
11
22
33
44
55
I would like at the press of a button that a loop starts to load one by one,each of these items like
WebView21.Source = New Uri("https://google.it" & ListBox1.Items.first & "rest of the url")
and after the webpage is loaded, it s supposed to extract it's html to check if a certain string is present with
Dim html As String
html = Await WebView21.ExecuteScriptAsync("document.documentElement.outerHTML;")
If html.Contains("Not found") Then
MsgBox("In Vacanza")
Else
MsgBox("Attivo")
End If
End Sub
after that, it goes back to the second listbox item, load the webview, check the html and so on.
My question is how can I loop the WebView in order to pick each of the items one by one and to proceed to do these little things in the while?
p.s. Once the loop arrives to the last listbox item, would it be possible to start it again from the first item?
Much thanks
edit1:
I'm trying with
Private ReadOnly resetEvent As New ManualResetEvent(False)
Async Sub scanWeb()
For Each listBoxElem As String In ListBox1.Items
resetEvent.Reset()
AddHandler WebView2.CoreWebView2.NavigationCompleted, AddressOf OnNavigationCompleted
WebView2.Source = New Uri("https://ikalogs.ru/tools/map/?page=1&server=22&world=10&state=active&search=city&allies%5B1%5D=&allies%5B2%5D=&allies%5B3%5D=&allies%5B4%5D=&nick=" & listBoxElem & "&ally=&island=&city=&x=&y=")
Await Task.Run(Sub() resetEvent.WaitOne())
RemoveHandler WebView2.CoreWebView2.NavigationCompleted, AddressOf OnNavigationCompleted
Dim html As String
html = Await WebView2.ExecuteScriptAsync("document.documentElement.outerHTML;")
If html.Contains("Not found") Then
DataGridView1.Rows.Add(listBoxElem, "IN vacanza")
Else
DataGridView1.Rows.Add(listBoxElem, "Attivo")
End If
Next
End Sub
Private Sub OnNavigationCompleted(sender As Object, e As CoreWebView2NavigationCompletedEventArgs)
resetEvent.Set()
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
WebView2 = New WebView2()
WebView2.EnsureCoreWebView2Async()
End Sub
but it seems the loop doesn't wait for the process to end and it goes straight to the next listbox item...
best way is to enumerate listBox items in a for-each loop : (I added an escape way -simple mouse clic on form - to quit loop)
Dim wStop As Boolean
sub scanWeb()
Do
For Each listBoxElem As String In ListBox1.Items
WebView21.Source = New Uri("https://google.it" & listBoxElem & "rest of the url")
'etc....
Next
Loop Until wStop = True
wStop = False
end sub
'way to stop scan
Private Sub form_clic(sender As Object, e As MouseEventArgs) Handles MyBase.MouseClick
wStop = True
End Sub
*** Update *****
The webview2 control is rather made to display data, and I have no experience on it.
Also I suggest you use a simpler method, based on System.Net.WebClient() and associated with threading.
Here is a start of code that works:
Dim wStop As Boolean
Dim i As Integer = 0
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim BackProcess = New Thread(Sub() Me.scanWeb())
BackProcess.Priority = ThreadPriority.Normal
BackProcess.Start()
end sub
Sub scanWeb()
Do While Not wStop
Dim WC As New System.Net.WebClient()
'change url for your need
Dim url As String = "https://www.google.fr/search?q=" & ListBox1.Items(i)
Dim s As System.IO.Stream = WC.OpenRead(url)
Dim sr As New System.IO.StreamReader(s)
Dim html As String = sr.ReadToEnd()
If html.Contains("Not found") Then 'beginInvoke allows the back task to communicate with UI
Me.BeginInvoke(Sub() DataGridView1.Rows.Add(ListBox1.Items(i), "In vacanza"))
Else
Me.BeginInvoke(Sub() DataGridView1.Rows.Add(ListBox1.Items(i), "Attivo"))
End If
i += 1
If i > ListBox1.Items.Count - 1 Then i = 0
Loop
End Sub
'button event to stop scanning
Private Sub stopScan_Click(sender As Object, e As EventArgs) Handles stopScan.Click
wStop = True
End Sub

VB .Net navigate each link and get a specific url

I'm having trouble using the web browser in VB .NET to navigate a list of URL's inside a multiline textbox, wait for them for load and get a specific URL (should contain a specific word).
What I have until now:
Private Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click
Dim webClient As New System.Net.WebClient
'Dim htmlDoc As New HtmlAgilityPack.HtmlDocument()
For Each strLine As String In TextBox4.Text.Split(vbCrLf)
Console.WriteLine("Turning False")
Console.WriteLine("----")
WebBrowser1.Navigate(strLine)
Console.WriteLine("Waiting for navigation - " & strLine)
Console.WriteLine("Navigated")
Next
For Each link In links
TextBox6.Text = TextBox6.Text & link & vbCrLf
Next
Dim lines As New List(Of String)(TextBox6.Lines)
For i As Integer = lines.Count - 1 To 1 Step -1
If lines(i) = lines(i - 1) Then
lines.RemoveAt(i)
End If
Next
TextBox6.Lines = lines.ToArray
End Sub
Private Sub WebBrowser1_DocumentCompleted(sender As Object, e As WebBrowserDocumentCompletedEventArgs) Handles WebBrowser1.DocumentCompleted
For Each ele As HtmlElement In WebBrowser1.Document.Links
'Get whatever text there is in the 'href' attribute
Dim eletarget As String = ele.GetAttribute("href")
'Add it to the listbox
If eletarget.Contains("cfsecure") Then
links.Add(eletarget)
'Carry on to the next link
End If
Next
End Sub
First of all, it seems it doesn't wait until fully loaded. After that, I don't get any link from what I asked (don't know if it's related to the first problem I have or any mistake in my code getting the href with the word "cfsecure").
Private Sub WebBrowser1_DocumentCompleted(sender As Object, e As WebBrowserDocumentCompletedEventArgs) Handles WebBrowser1.DocumentCompleted
For Each ele As HtmlElement In WebBrowser1.Document.Links
'Get whatever text there is in the 'href' attribute
Dim eletarget As String = ele.GetAttribute("href")
'Add it to the listbox
If eletarget.Contains("cfsecure") Then
links.Add(eletarget)
'Carry on to the next link
End If
Next
End Sub
What I'm missing here?

if the file not exits then return no error vb

I have start this application every things its work fine but i have a small bug but i can not find the solution to solve the error.
i have debug it and the error its because the file not exist
is there any way to me to populate my datagridview with all *.gif images From a directory and the check if its null or some thing like that.
What i mean is is there any way to my to populate all gif images found on the chose Directory?
in fact i have all ready try like this but i get one error "Provided column already belongs to the DataGridView control.
Well finaly i have found a solution to load all images from a directory to a datagridview programmatic
Here Is The Working Code
Public Class Form5
Private Sub addBtn_Click(sender As Object, e As EventArgs) Handles addBtn.Click
'Populate()
ShowImages()
End Sub
'CLEAR DATAGRIDVIEW
Private Sub clearBtn_Click(sender As Object, e As EventArgs) Handles clearBtn.Click
DataGridView1.Rows.Clear()
End Sub
'WHEN AN IMAGE IS CLICKED
Private Sub DataGridView1_CellContentClick(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView1.CellContentClick
MessageBox.Show("You Clicked Image At Col: " + e.ColumnIndex.ToString() + " Row: " + e.RowIndex.ToString())
End Sub
Private Sub Form5_Load(sender As Object, e As EventArgs) Handles MyBase.Load
End Sub
Public Sub ShowImages()
Dim directory As New System.IO.DirectoryInfo("C:\avitogifconverter\")
If directory.Exists Then
Dim pngFiles() As System.IO.FileInfo = directory.GetFiles("*.gif")
For Each pngFile As System.IO.FileInfo In pngFiles
If pngFile.Exists Then
Dim image = System.Drawing.Image.FromFile(pngFile.FullName)
Using image
Dim count = 1
' do something with the image like show in picture box
'CONSTRUCT IMG COLUMN
Dim imgCol As DataGridViewImageColumn = New DataGridViewImageColumn()
imgCol.HeaderText = "Photo"
imgCol.Name = "Col 1"
DataGridView1.Columns.Add(imgCol)
'CONSTRUCT ROWS
'FIRST ROW
Dim img As Image = System.Drawing.Image.FromFile(pngFile.FullName)
Dim row As Object() = New Object() {img, img, img}
DataGridView1.Rows.Add(row)
End Using
End If
Next
End If
End Sub
End Class
Using Directory.EnumerateFiles, you could do something like this:
Dim row = New List(Of Image)(3)
For Each filename In Directory.EnumerateFiles("C:\avitogifconverter", "*.gif")
row.Add(Image.FromFile(filename))
If row.Count = 3 Then
DataGridView1.Rows.Add(row.ToArray())
row.Clear()
End If
Next
If row.Count > 0 Then
DataGridView1.Rows.Add(row.ToArray())
row.Clear()
End If

For Loop works not working, or giving error. Works when conditions are reversed

I don't know if its the late hour, but I am working on the following array For Loop:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim pboxes() As PictureBox = {picMainImage, picImage2, picImage3, picImage4}
For i As Integer = 0 To pboxes.Count - 1
If pboxes(i).Image Is My.Resources.list Then
pboxes(i).Image = Nothing
End If
Next
End Sub
The loop is supposed to check if any of the picture boxes in the array have an Image called List stored on the Resources folder in them. If it does, set the image to Nothing. However, I run it and nothing happens., no errors, nothing.
So I reversed my For Loop as follows to see what happens:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim pboxes() As PictureBox = {picMainImage, picImage2, picImage3, picImage4}
For i As Integer = 0 To pboxes.Count - 1
If pboxes(i).Image Is Nothing Then
pboxes(i).Image = My.Resources.list
End If
Next
End Sub
This works but is not what I want, I want the opposite.
What am I doing wrong here?
One option is if you set the pictures in the box programatically, set My.Resources.list to be referenced by a global variable, ie Public pbList = My.Resources.list
Then, when you set the picture initially, use that variable, so: picMainImage.Image = pbList
Finally, in your If statement, you should then be able to check If pboxes(i) is pbList Then...
Once it becomes a variable, it seems to become static and therefore wherever you use it, it will always be the same.
EDIT: some actual code that I used a few months back:
In the module (outside sub)
Public pbimage As System.Drawing.Image = My.Resources.placeholder
Then in the Sub
If imgpath <> "" Then
Me.lblImg.ImageLocation = imgpath
Else
Me.lblImg.ImageLocation = Nothing
Me.lblImg.Image = pbimage
End If
and then this is what I use for all pictures without issues (its a function that I have run when you click on an image - if its the placeholder then you can browse for an image and save it to a data folder, otherwise it does nothing)
Private Sub changeImg(sender As Object, e As MouseEventArgs) Handles {ALL YOUR IMAGES}.Click
If TypeOf sender Is PictureBox Then
If DirectCast(sender, PictureBox).Image Is pbimage Then
Dim ofd As New OpenFileDialog
ofd.Title = "Please select image"
ofd.Filter = "Image Files|*.jpg"
If ofd.ShowDialog() = Windows.Forms.DialogResult.OK Then
Dim rn As New Random
Dim r As Long = rn.Next(111111, 999999)
Dim newfilename As String = My.Settings.dataPath & r.ToString & Format(Now, "ddmmyy") & ".jpg"
Try
FileCopy(ofd.FileName, newfilename)
DirectCast(sender, PictureBox).ImageLocation = newfilename
Catch ex As Exception
MessageBox.Show("Check permissions to the Data folder", "Permissions error")
End Try
End If
End If
End If
End Sub
Images cannot be compared that way because the image is copied into memory and will always be different even if the pixels match. Compare the pixels directly to find out if the image is the same.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim pboxes() As PictureBox = {picMainImage, picImage2, picImage3, picImage4}
For i As Integer = 0 To pboxes.Count - 1
If IsSameImage(pboxes(i).Image, My.Resources.list) = True Then
pboxes(i).Image = Nothing
End If
Next
End Sub
Public Function IsSameImage(ByVal oBitmap1 As Bitmap, ByVal oBitmap2 As Bitmap) As Boolean
For x = 0 To oBitmap1.Width - 1
For y = 0 To oBitmap2.Height - 1
If Not oBitmap1.GetPixel(x, y) = oBitmap2.GetPixel(x, y) Then
Return False
End If
Next
Next
Return True
End Function

Can't login to website (VB.net browser)

I try to login here: http://www.swagbucks.com/p/login
I've tried the following methods:
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
For Each element As HtmlElement In WebBrowser1.Document.GetElementsByTagName("input")
If element.Id = "sbxJxRegEmail" Then
Dim i = 0
Dim strLine = TextBox2.Text
element.OuterText = strLine
End If
If element.Id = "sbxJxRegPswd" Then
Dim i = 0
Dim strLine = TextBox3.Text
element.OuterText = strLine
End If
Next
End Sub
and then I tried this
WebBrowser1.Document.GetElementById("sbxJxRegEmail").SetAttribute("value", TextBox2.Text)
WebBrowser1.Document.GetElementById("sbxJxRegPswd").SetAttribute("value", TextBox3.Text)
WebBrowser1.Document.GetElementById("loginBtn").Focus()
WebBrowser1.Document.GetElementById("loginBtn").InvokeMember("click")
What happens is that the text is entered, but on the browser, it's not really there. It's hard to explain, but basically the username and password are just floating on top of the text boxes like some sort of ghost text and when I then click it, it disappears.
How do I fix this?
It's possible that they are masked inputs, probably need to set the inner text of those fields like so...
WebBrowser1.Document.All("Username").SetAttribute("value", "myusername")
WebBrowser1.Document.All("Password").SetAttribute("value", "mypassword")
Dim elements As HtmlElementCollection = (WebBrowser1.Document.All.GetElementsByName("Password"))
For Each element As HtmlElement In elements
element.InnerText = "mypassword"
Next
'You may have to do the same for your username/email