VB.NET WebBrowser control - how do you submit to default browser? - vb.net

I have a webbrowser control in my VBForm.
It looks for a website on my site and displays it.
There are form submit buttons in that WebBrowser1.
I would like it to be so that when they click a button in the WebBrowser1 Web page it will open their own browser to submit the form
How do i do this?
(yes, it's my website. i can change the HTML on the server if that is needed. )

answer is thanks to: Opening default web browser
and: vb.net WebBrowser links to Default Web Browser
and some trial and error. working result follows:
Private Sub WebBrowser1_Navigating(ByVal sender As Object, ByVal e As System.Windows.Forms.WebBrowserNavigatingEventArgs) Handles WebBrowser1.Navigating
'added a match string - if Allow is inside the URL link, then the WebBrowser control is allowed to navigate to it. otherwise use their browser.
dim Allow as string = "http://mysite.com"
If InStr(e.Url.ToString(), Allow) = 0 Then
' I'm trying here to cancel the event so that the WebBrowser1 control doesn't go there.
e.Cancel = True
' then start a new process with their default browser
System.Diagnostics.Process.Start(getDefaultBrowser(), e.Url.ToString())
End If
End Sub
Private Function getDefaultBrowser() As String
Dim browser As String = String.Empty
Dim key As RegistryKey = Nothing
Try
key = Registry.ClassesRoot.OpenSubKey("HTTP\shell\open\command", False)
'trim off quotes
browser = key.GetValue(Nothing).ToString().ToLower().Replace("""", "")
If Not browser.EndsWith("exe") Then
'get rid of everything after the ".exe"
browser = browser.Substring(0, browser.LastIndexOf(".exe") + 4)
End If
Finally
If key IsNot Nothing Then
key.Close()
End If
End Try
Return browser
End Function
I never would of solved it if Martin Parkin didn't post up that duplicate warning.
also - had to change my links to METHOD = GET, the post headers don't always translate in this manner.

Related

Download file after authenticated through WebBrowser

Background
So I am creating a VB .NET program that will basically login to a web page, do a bunch of button clicking, which results in the website generating an excel report that can be downloaded. I have successfully gone through all the steps to produce the file so now I am trying to create a method that will download the file behind the scenes without the "Save as" dialog appearing.
Details
I have managed to trap the download through the Navigating event of the Webbrowser control:
Public Sub a(sender As Object, e As WebBrowserNavigatingEventArgs) Handles WebBrowser1.Navigating
'intercept the excel download. Retrieve the url but cancel dialog
If e.Url.AbsoluteUri.Contains("fmsdownload") Then
Label3.Text = e.Url.AbsoluteUri
e.Cancel = True
'e.Url.AbsoluteUri = the temporarily generated file URL to download from
'INSERT DOWNLOAD METHOD HERE
End If
End Sub
I verified that the e.Url.AbsoluteUri is indeed the correct path. If I copy / paste this URL into Chrome, it downloads.
Question
So ultimately I am simply trying to find a way to download the file after the download link has been generated. Please take a look in the section below for what I have tried as I believe I am close to achieving success.
What I have tried (Please read before posting)
Method 1: My.Computer.Network.DownloadFile(URL,SAVEPATH). This results in the server kicking back The repote server returned an error: (403) Forbidden. This leads me to understand that the authentication isn't being passed which makes sense.
Method 2: I read on a stackoverflow post to try the URLMON to initiate the download (http://www.pinvoke.net/default.aspx/urlmon/URLDownloadToFile%20.html). I thought that this would have some promise but results in the error Unable to find an entry point named URLDownloadToFile in DLL 'URLMON.dll' Here is the code I have used for this method as it may be something simple I am missing:
Private Declare Sub URLDownloadToFile _
Lib "URLMON.dll" (
ByVal lpCaller As Long,
ByVal szUrl As String,
ByVal szFilename As String,
ByVal dwReserved As Long,
ByVal lpBindStatusCallback As Long)
Public Sub a(sender As Object, e As WebBrowserNavigatingEventArgs) Handles WebBrowser1.Navigating
'intercept the excel download. Retrieve the url but cancel dialog
If e.Url.AbsoluteUri.Contains("fmsdownload") Then
Label3.Text = e.Url.AbsoluteUri
e.Cancel = True
Try
Kill(My.Computer.FileSystem.SpecialDirectories.MyDocuments & "\download.xls")
Catch
End Try
URLDownloadToFile(0, e.Url.AbsoluteUri, My.Computer.FileSystem.SpecialDirectories.MyDocuments & "\download.xls", 0, 0)
End If
End Sub
Method 3: After some research it seems like the authentication is stored as cookies so I tried to retrieve the cookies and then provide them back to the WebClient since WebClient supports downloading files. Here is where I capture the cookies:
Dim cookie_collection() As String
Public Sub webbrowser1_documentcompleted(sender As Object, e As
WebBrowserDocumentCompletedEventArgs) Handles WebBrowser1.DocumentCompleted
If WebBrowser1.Document.Cookie Is Nothing Then
Else
Dim cookies As String() = WebBrowser1.Document.Cookie.Split({";"c}, StringSplitOptions.None)
For Each cookie As String In cookies
Dim name As String = cookie.Substring(0, cookie.IndexOf("="c)).TrimStart(" "c)
Dim value As String = cookie.Substring(cookie.IndexOf("="c) + 1)
If cookie_collection Is Nothing Then
ReDim cookie_collection(0)
Else
ReDim Preserve cookie_collection(cookie_collection.Length)
End If
cookie_collection(cookie_collection.Length - 1) = cookie
' MsgBox(cookie)
Next cookie
End If
End Sub
I verified that two cookies are captured during the authentication process:
So I try to reapply the cookies to my WebClient before downloading:
Public Sub a(sender As Object, e As WebBrowserNavigatingEventArgs) Handles WebBrowser1.Navigating
'intercept the excel download. Retrieve the url but cancel dialog
If e.Url.AbsoluteUri.Contains("fmsdownload") Then
Label3.Text = e.Url.AbsoluteUri
e.Cancel = True
Dim client As New System.Net.WebClient
For Each cookie As String In cookie_collection
client.Headers.Add(Net.HttpRequestHeader.Cookie, cookie)
Next
client.DownloadFile(e.Url.AbsoluteUri, My.Computer.FileSystem.SpecialDirectories.MyDocuments & "\download.xls")
End If
End Sub
This unfortunately results in the same error as before The repote server returned an error: (403) Forbidden which makes me realize the authentication isn't being passed still.
I know this is a big post but I feel like method 2 or method 3 should work so it may be possible I am missing something small (I hope).
In your last bit of code, where you use WebClient to retrieve the file, you currently add the cookies to the request as follows:
For Each cookie As String In cookie_collection
client.Headers.Add(Net.HttpRequestHeader.Cookie, cookie)
Next
However, there is only a single parameter in HTTP that includes all cookies at once, therefore you were overriding the previous cookies by pushing a new header for each cookie. You therefore do not need to extract the cookies by using String.Split, but rather pass the parameter with semicolons as it is, since HTTP should work everything out. Hope this solves your issue!
Edit: Here is what I think might work out:
Retrieve the cookies in the DocumentCompleted event like this (third bit of code):
Dim cookie_collection As String
Public Sub webbrowser1_documentcompleted(sender As Object, e As WebBrowserDocumentCompletedEventArgs) Handles WebBrowser1.DocumentCompleted
If WebBrowser1.Document.Cookie IsNot Nothing Then
Dim cookies As String = WebBrowser1.Document.Cookie
If cookie_collection = "" Then
cookie_collection = cookies
Else
cookie_collection &= ";" & cookies
End If
End If
End Sub
Then proceed by simply passing the cookie_collection field to the header:
...
Dim client As New System.Net.WebClient
client.Headers.Add(Net.HttpRequestHeader.Cookie, cookie_collection)
client.DownloadFile(e.Url.AbsoluteUri, My.Computer.FileSystem.SpecialDirectories.MyDocuments & "\download.xls")
...

How to fill a WebForm and click the submit Button with a WebBrowser control?

How can I click this SUBMIT button using a WebBrowser control?
I've tried with:
For Each divSect As HtmlElement In WebBrowser1.Document.GetElementsByTagName("button")
If divSect.OuterHtml.Contains("Accedi") Then
For Each elem As HtmlElement In divSect.Children
If elem.GetAttribute("type") = "button" Then
elem.InvokeMember("click")
End If
Next
End If
Next
but it doesn't return anything.
Here's a sample procedure to perform a WebForm LogIn using a WebBrowser control.
▶ Note: I suggest to activate the WebBrowser Emulation Advanced Features beforehand, in case its need. Read a description here (see the WebBrowserAdvancedFetures class):
(The FEATURE_GPU_RENDERING Key may not exist, so it may be necessary to create it first)
Subscribe to the WebBrowser.DocumentCompleted event before navigating to an Address
As describe in How to get an HtmlElement value inside Frames/IFrames?, the Document may be actually composed of more than one Frame/IFrame (the latter, quite common). If that's the case, you need to handle the DocumentCompleted more than once, since each Frame/IFrame has its own Document
When the event is raised, check whether the WebBrowser.ReadyState is WebBrowserReadyState.Complete: return if its not (we don't want to handle partial documents).
When the current Document is complete find a Form with a specific ID or class name: that's the Login Form we want to fill in.
When the Form is found, parse its Document and to select the INPUT elements that require a value.
If all elements are found and their values has been set, find the SUBMIT Button and call its InvokeMember() method, specifying the click handler to complete the procedure and activate the Form POST method.
When the Button is clicked, the WebBrowser is redirected to a landing page, so we remove the Handler of the DocumentCompleted event: we're done here, handling this event is no longer need.
▶ Set [WebBrowser].ScriptErrorsSuppressed = True in the Form's Designer.
Private Sub btnNavigate_Click(sender As Object, e As EventArgs) Handles btnNavigate.Click
AddHandler webBrowser1.DocumentCompleted, AddressOf Browser_DocumentCompleted
webBrowser1.Navigate("https://SomeAddress.com")
End Sub
Private Sub Browser_DocumentCompleted(sender As Object, e As WebBrowserDocumentCompletedEventArgs)
Dim browser = DirectCast(sender, WebBrowser)
If browser.ReadyState <> WebBrowserReadyState.Complete Then Return
' Select a Form with a specific className
Dim form = browser.Document.Forms.OfType(Of HtmlElement).FirstOrDefault(Function(frm) frm.GetAttribute("className").StartsWith("form-login"))
' Not found at this point, try later
If form Is Nothing Then Return
' Select the element by ID or by className or whatever
Dim userId = form.Document.GetElementById("[The UserId Input's ID]")
' Same for other input elements
Dim userPwd = form.Document.GetElementById("[The Password Input's ID]")
If userId Is Nothing OrElse userPwd Is Nothing Then Return
' Set the value of both Input elements. Note that a validation procedure
' may require that you set both the Value and the InnerText
userId.SetAttribute("value", "[The User LogIn ID]")
'userId.InnerText = "[The User LogIn ID]"
userPwd.SetAttribute("value", "[The User LogIn Password]")
'userPwd.InnerText = "[The User LogIn Password]"
' Filter (fail-safe) the SUBMIT button by className, since - here - it has no ID
Dim submit = browser.Document.GetElementsByTagName("button").OfType(Of HtmlElement).
FirstOrDefault(Function(elm) elm.GetAttribute("type").
Equals("submit") AndAlso elm.GetAttribute("className").Contains("bt-label"))
' The SUBMIT Button was found: click it. Also remove the handler: we're done here
' The WebBrowser is redirected to a landing page, this event is no longer needed
If submit IsNot Nothing Then
RemoveHandler browser.DocumentCompleted, AddressOf Browser_DocumentCompleted
submit.InvokeMember("click")
End If
End Sub

Using Windows Forms to open a browser and call a Javascript function

I'm new to this so please bear with me. I am using a VB.NET (2.0) Windows Forms application.
On Form_Load(), I open up IE browser, which then navigates to a particular URL with a login form. It passes the u/n and p/w values to this form and gets the button id and calls the click function on it, causing the browser to redirect to the web site as a user. It then executes a script on that page, which displays a bulk upload control.
I want to be able to get/set the value in the text box on this page.
'-->>> theTextBox = Nothing. After executing the script, the bulk update div is 'created in the page by the script. If we do a View Source, we can see an element with ID as 'TXT_UPLOAD as below.
'INPUT type="TEXT" id="TXT_UPLOAD" size="78" onblur="checkFileType(this,this.value, 'true)"
Here is my code:
Dim IE As New Object
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim URL As String = "http://someurl.com/"
Try
IE = CreateObject("InternetExplorer.Application")
IE.Visible = True
IE.Navigate("https://someurl.com/Login.aspx?")
Threading.Thread.Sleep(3000)
WaitUntil(IE.Document)
IE.Document.getElementById("tb_login").value = "username"
IE.Document.getElementById("tb_password").value = "password"
Dim theButton
theButton = IE.Document.getElementById("btn_login")
theButton.Click()
Threading.Thread.Sleep(5000)
WaitUntil(IE.Document)
IE.Document.parentWindow.execScript("parent.showApplication('Bulk Update', 712030600,-1,712000000,1);")
Dim theTextBox
theTextBox = IE.Document.getElementById("TXT_UPLOAD")
theTextBox.Focus()
Debug.Print(theTextBox.value)
theTextBox.Value = "C:\NV\CV\CLWR_NA_CHG_UPLOAD_2014313.csv"
IE.Document.parentWindow.execScript("parent.logOff();")
Catch ex As Exception
MsgBox(ex.ToString)
Threading.Thread.Sleep(5000)
WaitUntil(IE.Document)
IE.Document.parentWindow.execScript("parent.logOff();")
End Try
IE = Nothing
'IE.kill()
'IE.Quit()
End
End Sub

Visual Basic - Web browser load URLs from text

i am not so great with Visual basic, but i need some help on creating a web browser that would load several links import from a text file, and for the web browser to navigate to them. This is what i have so far
Dim link As String = OpenFileDialog2.FileName
Dim links As String = IO.File.ReadAllText(link)
MsgBox(links)
WebBrowser1.Navigate(links)
You help means a lot. Thank You.
The WebBrowser Control either will show the webpage in the Control which will limit you to one page, or you can tell it to open the pages in separate windows which will open an Internet Explorer window for each link. I also used the File.ReadAllLines Method in order to get an array of the Links so that you can iterate through the Web Pages . This works for me but might not be what you are wanting.
Public Class Form1
Dim wb As New WebBrowser
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
Dim filename As String = "C:\temp\links.txt"
Dim links As String() = IO.File.ReadAllLines(filename)
For Each link As String In links
wb.Navigate(link, True)
Next
End Sub
Public Sub New()
InitializeComponent()
Controls.Add(wb)
wb.Dock = DockStyle.Fill
End Sub
End Class
My text file called Links.txt looks like this:
www.google.com
www.msdn.com
www.bing.com

How to stop a user navigating away in a webbrowser?

I am currently building a webbrowser that only loads one page, but I don't want the user to be able to navigate away by clicking advertisement links, as I don't want them to be able to surf the net, clicking links could eventually lead them back to Google to search for what they like if they are clever enough!
Any ideas?
When the page is done loading, intercept the links :
Dim olink As HtmlElement
Dim olinks As HtmlElementCollection = WB1.Document.Links
For Each olink In olinks
olink.AttachEventHandler("onclick", AddressOf LinkClicked)
Next
Then add a function :
Private Sub LinkClicked(ByVal sender As Object, ByVal e As EventArgs)
If txtAddress.Enabled = True Then
Dim link As HtmlElement = WB1.Document.ActiveElement
Dim url As String = link.GetAttribute("href")
MsgBox("Link Clicked: " & link.InnerText & vbCrLf & "Destination: " & url)
WB1.Navigate(url, False)
End If
End Sub
Sounds like more of a sysadmin issue, to me.
I'm not familiar with any of the proper software. but if you set up the OS so that it will only be allowed to access webpages on a "whitelist", then there will be no need to write a custom web browser.
If you have a browser component in you project, you should add an event listener for your browser URL, if it changed, redirect to your desired page.