VB.NET - Navigate webpage with specified user-agent? - vb.net

I'm trying to change current user gaent to different user-agent. This one naviagtes the webpage, however, doesnt change the user-agent.
Dim webBrowser1 As Object
webBrowser1 = CreateObject("InternetExplorer.Application")
webBrowser1.Navigate("http://www.example.org", Nothing, Nothing, "User-Agent: blabla")
What is the correct way to do that ?

You create a System.Net.Webclient instead and give it the wanted headers.
Imports System.Net
Module Module1
Sub Main()
' Resource acquisition statement.
Using client As New WebClient
' Set one of the headers.
client.Headers("User-Agent") = "Mozilla/4.0"
' Download data as byte array.
Dim arr() As Byte = client.DownloadData("http://www.dotnetperls.com/")
' Display result.
Console.WriteLine(arr.Length)
End Using
End Sub
End Module
Source: http://www.dotnetperls.com/webclient-vbnet

Related

How to check for strings in a panel?

I'm making a string checker which should check for a string on a website.
I'm using a panel instead of a web browser because I merged chromium with CefSharp into it.
Now I can't figure out how to check for a string in the panel.
I tried creating a different type of variable, but the variable comes from a file.
I also tried for normal text without variables.
Both didn't work.
Public Sub New()
Dim site As String = File.ReadAllText("webstore.shd")
Dim id As String = File.ReadAllText("ID.shd")
InitializeComponent()
Dim settings As New CefSettings()
CefSharp.Cef.Initialize(settings)
browser = New ChromiumWebBrowser(site) With {
.Dock = DockStyle.Fill
}
Panel1.Controls.Add(browser)
If Panel1.Contains(id) Then
' I am stuck right here.
msgbox("Succes")
Else
msgbox("Nope")
End If
End Sub
I expected that the program would search for the variable in the panel, but it wouldn't do that.

Populate Web Form From VB Application

I have created a simple FORM in VB.NET that takes some details and then needs to log in to 3 locations using this information.
At the moment I have the code so it takes this data from the textBoxs and assigns them to 4 different variables. From there I have also opened up the three different websites.
I am having difficulties finding how I will take the variables and then populate the corresponding field on the web application. Any suggestions?
My Code:
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
'Define Store variable
Dim Store As String
Store = Me.TextBox1.Text
'Define IP Address variable
Dim IPAddress As String
IPAddress = Me.TextBox2.Text
'Define Username variable
Dim Username As String
Username = Me.TextBox3.Text
'Define Password variable
Dim Password As String
Password = Me.TextBox4.Text
' Open Store Specific URL 1
Dim WebAddress1 As String = "http://" & IPAddress & ":"
Process.Start(WebAddress1)
getElementByName
' Open Store Specific URL 2
Dim WebAddress2 As String = "http://somedomain2.com"
Process.Start(WebAddress2)
' Open Store Specific URL 3
Dim WebAddress3 As String = "http://somedomain3.com"
Process.Start(WebAddress3)
End Sub
End Class
What you need to do is identify the element name that you want to populate. This can typically done by going to the web page, and pressing View Source (changes by web browser, some you can right click and it will be there, some you can access through the settings button.)
Once looking at the source, you will want to find the object (usually a text box or something along those lines) where you want to send the information. Usually these boxes have titles, like Username, or Password. So I would recommend doing a Ctrl + F search based on the information you can see on the site. I see in your code you have GetElementByName, and that's exactly what you'll do. You will want to store
Here's an example code:
Dim IE As Object 'Internet explorer object
Dim objCollection As Object 'Variable used for cycling through different elements
'Create IE Object
IE = CreateObject("InternetExplorer.Application")
IE.Visible = True
IE.Navigate("https://somewebsite.com/") 'Your website
Do While IE.Busy
Application.DoEvents() 'This allows the site to load first
Loop
'Find the field you are looking for and store it into the objCollection variable
objCollection = IE.document.getelementsbyname("CustomerInfo.AccountNumber") 'The "CustomerInfo.AccountNumber" is the name of the element I looked for in this case.
'Call element, and set value equal to the data you have from your form
objCollection(0).Value = MainForm.tbLoan.Text
' Clean up
IE = Nothing
objCollection = Nothing
This should be a good start for you. There are multiple resources on this site that might be able to give you additional information when it comes to entering data into websites using vb.net.
Hopefully this helps!

System.UnauthorizedAccessException only using multithreading

I wrote a code to parse some Web tables.
I get some web tables into an IHTMLElementCollection using Internet Explorer with this code:
TabWeb = IE.document.getelementsbytagname("table")
Then I use a sub who gets an object containing the IHTMLElementCollection and some other data:
Private Sub TblParsing(ByVal ArrVal() As Object)
Dim WTab As mshtml.IHTMLElementCollection = ArrVal(0)
'some code
End sub
My issue is: if I simply "call" this code, it works correctly:
Call TblParsing({WTab, LiRow})
but, if I try to run it into a threadpool:
ThreadPool.QueueUserWorkItem(New WaitCallback(AddressOf TblParsing), {WTab, LiRow})
the code fails and give me multiple
System.UnauthorizedAccessException
This happens on (each of) these code rows:
Rws = WTab(RifWT("Disc")).Rows.Length
If Not IsError(WTab(6).Cells(1).innertext) Then
Ogg_W = WTab(6).Cells(1).innertext
My goal is to navigate to another web page while my sub perform parsing.
I want to clarify that:
1) I've tryed to send the entire HTML to the sub and get it into a webbrowser but it didn't work because it isn't possible to cast from System.Windows.Forms.HtmlElementCollection to mshtml.IHTMLElementCollection (or I wasn't able to do it);
2) I can't use WebRequest and similar: I'm forced to use InternetExplorer;
3) I can't use System.Windows.Forms.HtmlElementCollection because my parsing code uses Cells, Rows and so on that are unavailable (and I don't want to rewrite all my parsing code)
EDIT:
Ok, I modified my code using answer hints as below:
'This in the caller sub
Dim IE As Object = CreateObject("internetexplorer.application")
'...some code
Dim IE_Body As String = IE.document.body.innerhtml
ThreadPool.QueueUserWorkItem(New WaitCallback(AddressOf TblParsing_2), {IE_Body, LiRow})
'...some code
'This is the called sub
Private Sub TblParsing_2(ByVal ArrVal() As Object)
Dim domDoc As New mshtml.HTMLDocument
Dim domDoc2 As mshtml.IHTMLDocument2 = CType(domDoc, mshtml.IHTMLDocument2)
domDoc2.write(ArrVal(0))
Dim body As mshtml.IHTMLElement2 = CType(domDoc2.body, mshtml.IHTMLElement2)
Dim TabWeb As mshtml.IHTMLElementCollection = body.getElementsByTagName("TABLE")
'...some code
I get no errors but I'm not sure that it's all right because I tryed to use IE_Body string into webbrowser and it throws errors in the webpage (it shows a popup and I can ignore errors).
Am I using the right way to get Html from Internet Explorer into a string?
EDIT2:
I changed my code to:
Dim IE As New SHDocVw.InternetExplorer
'... some code
Dim sourceIDoc3 As mshtml.IHTMLDocument3 = CType(IE.Document, mshtml.IHTMLDocument3)
Dim html As String = sourceIDoc3.documentElement.outerHTML
ThreadPool.QueueUserWorkItem(New WaitCallback(AddressOf TblParsing_2), {html, LiRow})
'... some code
Private Sub TblParsing_2(ByVal ArrVal() As Object)
Dim domDoc As New mshtml.HTMLDocument
Dim domDoc2 As mshtml.IHTMLDocument2 = CType(domDoc, mshtml.IHTMLDocument2)
domDoc2.write(ArrVal(0))
Dim body As mshtml.IHTMLElement2 = CType(domDoc2.body, mshtml.IHTMLElement2)
Dim TabWeb As mshtml.IHTMLElementCollection = body.getElementsByTagName("TABLE")
But I get an error PopUp like (I tryed to translate it):
Title:
Web page error
Text:
Debug this page?
This page contains errors that might prevent the proper display or function properly.
If you are not testing the web page, click No.
two checkboxes
do not show this message again
Use script debugger built-in Internet Explorer
It's the same error I got trying to get Html text into a WebBrowser.
But, If I could ignore this error, I think the code could work!
While the pop is showing I get error on
Dim domDoc As New mshtml.HTMLDocument
Error text translated is:
Retrieving the COM class factory for component with CLSID {25336920-03F9-11CF-8FD0-00AA00686F13} failed due to the following error: The 8,001,010th message filter indicated that the application is busy. (Exception from HRESULT: 0x8001010A (RPC_E_SERVERCALL_RETRYLATER)).
Note that I've alredy set IE.silent = True
Edit: There was confusion as to what the OP meant by "Internet Explorer". I originally assumed that it meant the WinForm Webbrowser control; however the OP is creating the COM browser directly instead of using the .Net wrapper.
To get the browser document's defining HTML, you can cast the document against the mshtml.IHTMLDocument3 interface to expose the documentElement property.
Dim ie As New SHDocVw.InternetExplorer ' Proj COM Ref: Microsoft Internet Controls
ie.Navigate("some url")
' ... other stuff
Dim sourceIDoc3 As mshtml.IHTMLDocument3 = CType(ie.Document, mshtml.IHTMLDocument3)
Dim html As String = sourceIDoc3.documentElement.outerHTML
End Edit.
The following is based on my comment above. You use the WebBrowser.DocumentText property to create a mshtml.HTMLDocument.
Use this property when you want to manipulate the contents of an HTML page displayed in the WebBrowser control using string processing tools.
Once you extract this property as a String, there is no connection to the WebBrowser control and you can process the data in any thread you want.
Dim html As String = WebBrowser1.DocumentText
Dim domDoc As New mshtml.HTMLDocument
Dim domDoc2 As mshtml.IHTMLDocument2 = CType(domDoc, mshtml.IHTMLDocument2)
domDoc2.write(html)
Dim body As mshtml.IHTMLElement2 = CType(domDoc2.body, mshtml.IHTMLElement2)
Dim tables As mshtml.IHTMLElementCollection = body.getElementsByTagName("TABLE")
' ... do something
' cleanup COM objects
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(body)
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(tables)
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(domDoc)
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(domDoc2)

How to close parent form and open child?

Hey guys before I was just hiding the parent form, but now when I try to read from the parent file it says it can't because it's already running in a process. I followed some tutorial and it said to go to the project properties and have the application stop running when all the forms are closed.
But now since I did that it says the directory can't be found probably because I am reading the input from the parent form. Anyways here is my code
Dim writeFile1 As StreamWriter = New StreamWriter(File.OpenWrite("C:\Users\Nick\Documents\Visual Studio 2010\Projects\LoginFixed\Accounts\" + frmLogin.txtUser.Text))
How should I go about doing this?
Edit:
Private Sub btnHunter_Click(sender As System.Object, e As System.EventArgs) Handles btnHunter.Click
selection = "Hunter"
writeData.classSelection()
End Sub
This is what I have when the button is clicked.
Here is the classSelection sub:
Public Sub classSelection()
If frmClass.selection = "Hunter" Then
writeFile1.WriteLine(frmClass.selection)
End If
If frmClass.selection = "Gatherer" Then
writeFile1.WriteLine(frmClass.selection)
End If
If frmClass.selection = "Farmer" Then
writeFile1.WriteLine(frmClass.selection)
End If
writeFile1.Close()
End Sub
The error points to this line:
If frmClass.selection = "Hunter" Then
Saying part of the file path cannot be found.
If you want to read input textbox in closed parent form, you have to declare public var
Make a new module in your project .. and add this
public sLogin as String
And before you hide or close frmLogin .. add this
sLogin = txtUser.Text
So, you could change your code with
Dim writeFile1 As StreamWriter = New StreamWriter(File.OpenWrite("C:\Users\Nick\Documents\Visual Studio 2010\Projects\LoginFixed\Accounts\" & sLogin))
matzone has given you a good hint. And to check exactly what your path is, just add a MessageBox using variables :
Dim writePath1 As String
Dim writeFile1 As StreamWriter
writePath1 = "C:\Users\Nick\Documents\Visual Studio 2010\Projects\LoginFixed\Accounts\" & sLogin
If MessageBox.Show(writePath1, "Continue ?", MessageBoxButtons.YesNo) = DialogResult.Yes Then
writeFile1 = New StreamWriter(File.OpenWrite(writePath1))
' ...
writeFile1.Close() ' Very important ! Adrian pointed it out.
End If
^^ and if it works, you can discard the Dialog test or replace it by some test code like If File.Exists(...)
However, I don't understand wether you want to close the parent Form or hide it. It's different !
Closing the parent Form will discard any access to parent Form members, including txtUser.Text.
If you want to close the parent Form, the ChildForm should not be a child of that parent you are trying to close, or you must just hide the parent Form :
frmLogin.Hide() ' Not frmLogin.Close()
If you close frmLogin, frmLogin.txtUser won't be accessible, or use sLogin provided by matzone instead. Alternatively, you should pass frmLogin.txtUser.Text value to a custom property of ChildForm.
Imports System.IO
Public Partial Class ChildForm1
' Inherits System.Windows.Form
' ...
Private _txtUserFile As String
Public WriteOnly Property TxtUserFile() As String
Set(ByVal NewFileName As String)
_txtUserFile = NewFileName
End Set
End Property
Public Sub LoadFile()
Dim writeFile1 As StreamWriter = New StreamWriter(File.OpenWrite("C:\Users\Nick\Documents\Visual Studio 2010\Projects\LoginFixed\Accounts\" & txtUserFile))
' ...
writeFile1.Close()
End sub
' ...
End Class
Then use this in parent Form :
MyChildForm.TxtUserFile = Me.txtUser.Text
' Me.Close() ' This will definately KILL Form1 (the parent one)
Me.Hide() ' Always use Hide() until you'll terminate your Application
MyChildForm.Show()
MyChildForm.LoadFile()
^^ but this is not a good code either ! Your problem remains unclear (at least for me)
"Still saying it can't find part of the path", then check the path..
Does the file actually exists ?
Does the path contains glitch ? (use the provided MessageBox test)
Does your account can access that directory ? (Windows configuration and account levels)
Well !
In fact, the problem could be somewhere else.
For example, I was able to reproduce your exception by providing an empty string [""] as the value of, either :
frmLogin.txtUser.Text ' = ""
' or
sLogin ' = ""
' or
txtUserFile ' = ""
In fact, I get the "Could not find a part of the path..." exception because the StreamWriter couldn'd read/write to a File, as I didn't provided a valid FileName for that file. As the filename parameter was an empty string "", the provided path for StreamWriter was just representing a directory instead of a file and an exception was raised.
Now, you should check wether you have a valid path before building a new instance of StreamWriter to get sure you are actually pointing to a File ?
Dim writeFile1 As StreamWriter
Dim MyEntirePath As String = "C:\Users\...\Accounts\" + frmLogin.txtUser.Text
MessageBox.Show(MyEntirePath) ' would be enough to be sure your path is correct
' Some test code here...
If everythingOK then ' create the StreamWriter...
writeFile1 = New StreamWriter(MyEntirePath)
' ...
' ...
Also, it's not a good idea to create your streamwriter, and use it in another part/method of your code. You never known if one day, you'll change your code, and forget to make the link between
Dim writeFile1 As StreamWriter = New StreamWriter(File.OpenWrite("C:\Users\Nick\Documents\Visual Studio 2010\Projects\LoginFixed\Accounts\" + frmLogin.txtUser.Text))
' plus
Private Sub btnHunter_Click(sender As System.Object, e As System.EventArgs)
...
End Sub
' plus
Public Sub classSelection()
...
writeFile1.Close()
End Sub
^^ too much "here and there"...
You'll obviously also get an exception if you try to click btnHunter twice.. I don't know what is the purpose of your code nor how it works, it looks like a game.. But I would use File.Exist(..) checks, create the file before, if none, and put that in a Try/Catch to check if I eventually don't have administrator rights to write to that directory. Otherwise, make a code that allow user to read/write files to a custom folder. Andalso, you have :
Application.StartupPath
^^ Very usefull, like :
Dim MyFilePath As String = Application.StartupPath + "\Datas\MyText.txt"
After two weeks of coding, I usually forget where I put those "C:\blabla.." or "D:\gnagna\" or what classes actually uses those absolute reference paths. I've dropped this way of getting directories long ago since the day I moved to Win7 on another computer and all such applications I developped using that approach was doomed...

Download URL Contents Directly into String (VB6) WITHOUT Saving to Disk

Basically, I want to download the contents of a particular URL (basically, just HTML codes in the form of a String) into my VB6 String variable. However, there are some conditions.
I know about the URLDownloadToFile Function - however, this requires that you save the downloaded file/HTML onto a file location on disk before you can read it into a String variable, this is not an option for me and I do not want to do this.
The other thing is, if I need to use an external library, it must already come with all versions of Windows from XP and onwards, I cannot use a control or library that I am required to ship, package and distribute even if it is free, this is not an option and I do not want to do this. So, I cannot use the MSINET.OCX (Internet Transfer) Control's .OpenURL() function (which simply returns contents into a String), as it does not come with Windows.
Is there a way to be able to do this with the Windows API, URLMON or something else that is pre-loaded into or comes with Windows, or a way to do it in VB6 (SP6) entirely?
If so, I would appreciate direction, because even after one hour of googling, the only examples I've found are references to URLDownloadToFile (which requires saving on disk before being ale to place into a String) and MsInet.OpenURL (which requires that I ship and distribute MSINET.OCX, which I cannot and don't want to do).
Surely there has got to be an elegant way to be able to do this? I can do it in VB.NET without an issue, but obviously don't have the luxury of the .NET framework in VB6 - any ideas?
Update:
I have found this: http://www.freevbcode.com/ShowCode.asp?ID=1252
however it says that the displayed function may not return the entire
page and links to a Microsoft bug report or kb article explaining
this. Also, I understand this is based off wininet.dll - and I'm
wondering which versions of Windows does WinInet.dll come packaged
with? Windows XP & beyond? Does it come with Windows 7 and/or Windows
8?
This is how I did it with VB6 a few years ago:
Private Function GetHTMLSource(ByVal sURL As String) As String
Dim xmlHttp As Object
Set xmlHttp = CreateObject("MSXML2.XmlHttp")
xmlHttp.Open "GET", sURL, False
xmlHttp.send
GetHTMLSource = xmlHttp.responseText
Set xmlHttp = Nothing
End Function
If you want to do this with pure VB, and no IE, then you can take advantage of a little-used features of the VB UserControl - async properties.
Create a new UserControl, and call it something like UrlDownloader. Set the InvisibleAtRuntime property to True. Add the following code to it:
Option Explicit
Private Const m_ksProp_Data As String = "Data"
Private m_bAsync As Boolean
Private m_sURL As String
Public Event AsyncReadProgress(ByRef the_abytData() As Byte)
Public Event AsyncReadComplete(ByRef the_abytData() As Byte)
Public Property Let Async(ByVal the_bValue As Boolean)
m_bAsync = the_bValue
End Property
Public Property Get Async() As Boolean
Async = m_bAsync
End Property
Public Property Let URL(ByVal the_sValue As String)
m_sURL = the_sValue
End Property
Public Property Get URL() As String
URL = m_sURL
End Property
Public Sub Download()
UserControl.AsyncRead m_sURL, vbAsyncTypeByteArray, m_ksProp_Data, IIf(m_bAsync, 0&, vbAsyncReadSynchronousDownload)
End Sub
Private Sub UserControl_AsyncReadComplete(AsyncProp As AsyncProperty)
If AsyncProp.PropertyName = m_ksProp_Data Then
RaiseEvent AsyncReadComplete(AsyncProp.Value)
End If
End Sub
Private Sub UserControl_AsyncReadProgress(AsyncProp As AsyncProperty)
If AsyncProp.PropertyName = m_ksProp_Data Then
Select Case AsyncProp.StatusCode
Case vbAsyncStatusCodeBeginDownloadData, vbAsyncStatusCodeDownloadingData, vbAsyncStatusCodeEndDownloadData
RaiseEvent AsyncReadProgress(AsyncProp.Value)
End Select
End If
End Sub
To use this control, stick it on a form and use the following code:
Option Explicit
Private Sub Command1_Click()
XDownload1.Async = False
XDownload1.URL = "http://www.google.co.uk"
XDownload1.Download
End Sub
Private Sub XDownload1_AsyncReadProgress(the_abytData() As Byte)
Debug.Print StrConv(the_abytData(), vbUnicode)
End Sub
Suffice to say, you can customise this to your hearts content. It can tell (using the AyncProp object) whether the file is cached, and other useful information. It even has a special mode in which you can download GIF, JPG and BMP files and return them as a StdPicture object!
One alternative is using Internet Explorer.
Dim ex As InternetExplorer
Dim hd As HTMLDocument
Dim s As String
Set ex = New InternetExplorer
With ex
.Navigate "http://donttrack.us/"
.Visible = 1
Set hd = .Document
s = hd.body.innerText ' assuming you just want the text
's = hd.body.innerHTML ' if you want the HTML
End With
EDIT: For the above early binding to work you need to set references to "Microsoft Internet Controls" and "Microsoft HTML Object Library" (Tools > References). You could also use late binding, but to be honest, I forget what the proper class names are; maybe someone smart will edit this answer :-)