VB.NET 2008 - Input to data to website controls and download results - vb.net

this is my first Q on this website so let me know if I have missed any important details, and thanks in advance.
I have been asked to access a website and download the results from a user-inputted form. The website asks for a username/password and once accepted, several questions which are used to generate several answers.
Since I am unfamiliar with this area I have set up a simple windows form to tinker around with websites and try to pick things up. I have used a webbrowser control and a button to use it to view the website in question.
When I try to view the website through the control, I just get script errors and nothing loads up. I am guessing I am missing certain plug-ins on my form that IE can handle without errors. Is there anyway I can identify what these are and figure out what to do next? I am stumped.
The script errors are:
"Expected identifier, string or number" and
"The value of the property 'setsection' is null or undefined"
Both ask if I want to continue running scripts on the page. But it works in IE and I cannot see why my control is so different. It actually request a username and password which works fine, it is the next step that errors.
I can provide screenies or an extract from the website source html if needed.
Thanks,
Fwiw my code is:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
'WebBrowser1.ScriptErrorsSuppressed = True
WebBrowser1.Navigate("http://website.com")
'WebBrowser1.Navigate("http://www.google.com")
End Sub

Thanks for Noseratio I have managed to get somewhere with this.
Even though the errors I was getting seemed to be related to some XML/Java/Whatever functionality going askew it was actually because my webbrowser control was using ie 7.0
I forced it into using ie 9 and all is now well. So, using my above example I basically did something like this:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
'WebBrowser1.ScriptErrorsSuppressed = True
BrowserUpdate()
WebBrowser1.Navigate("http://website.com")
'WebBrowser1.Navigate("http://www.google.com")
End Sub
Sub BrowserUpdate()
Try
Dim IEVAlue As String = 9000 ' can be: 9999 , 9000, 8888, 8000, 7000
Dim targetApplication As String = Process.GetCurrentProcess.ToString & ".exe"
Dim localMachine As Microsoft.Win32.RegistryKey = Microsoft.Win32.Registry.LocalMachine
Dim parentKeyLocation As String = "SOFTWARE\Microsoft\Internet Explorer\MAIN\FeatureControl"
Dim keyName As String = "FEATURE_BROWSER_EMULATION"
Dim subKey As Microsoft.Win32.RegistryKey = localMachine.CreateSubKey(parentKeyLocation & "\" & keyName)
subKey.SetValue(targetApplication, IEVAlue, Microsoft.Win32.RegistryValueKind.DWord)
Catch ex As Exception
'Blah blah here
End Try
End Sub

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")
...

Equals Not Working VB.Net

I am trying to compare two strings that I know are equal to each other, but it is always skipping to the else. I've tried everything, .Equals, =, IsNot, they all don't work! The frustrating part is that I know the strings are equal! Please take a look at my code and see if it there is possible anything wrong with it.
Public Class Form1
Dim log As String
WithEvents xworker As New System.ComponentModel.BackgroundWorker
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
xworker.RunWorkerAsync()
End Sub
Private Sub xWorker_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles xworker.DoWork
Dim qWorker = CType(sender, System.ComponentModel.BackgroundWorker)
Dim client As New Net.WebClient
log = client.DownloadString("http://########/log.txt")
End Sub
Private Sub xWorker_Completed(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles xworker.RunWorkerCompleted
If log.Equals(RichTextBox1.Text) Then
xworker.RunWorkerAsync()
Else
RichTextBox1.Text = log
xworker.RunWorkerAsync()
End If
End Sub
End Class
You needed to listen to #SLaks and #Hans Passant, they were right on the money.
I setup your code sample and it worked correctly if the source log.txt file didn't have a line terminator in it. Once I added the line terminator I got the results your are getting.
From the command window:
>? RichTextBox1.Text.Length
14
>? log.length
15
Using the QuickWatch window, and TABing until the Value field was selected:
Log result:
"log test 1234" & vbCrLf & ""
RichTextBox result:
"log test 1234" & vbLf & ""
The fix to the problem depends on what will actually get written to the log.txt file. I assume that "log test 1234" is just development code. If you are only interested in a single line as a result code then make sure you are not writing a line terminator. If your result codes are more complicated then you will need to do more parsing on the result than just an Equals compare.
Try this instead.
If log.ToLower().Trim() = RichTextBox1.Text.ToLower().Trim() Then
I think this is case sensitve compare. You should convert both of the strings to upper or to lower and then compare them
If Log.ToLower() = RichTextBox1.Text.ToLower() Then
Or you can use String.Compare method and set third param to true to ignore case
If String.Compare(log, RichTextBox1.Text, True) = 0 Then
I've read that the RichTextBox can change line endings when Text gets set. So the Text property might be returning a string that is different than what was set. I haven't been able to verify, but you can probably devise a quick test of this theory.

google map is not showing in vb.net application

i have written a simple vb application to show the google map . But it is not working properly.
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim City As String = TextBox1.Text
Try
Dim queryAddress As New StringBuilder
queryAddress.Append("http://maps.google.com/maps?q=")
If TextBox1.Text = String.Empty Then
queryAddress.Append(City + " , " & " + ")
End If
WebBrowser1.Navigate(queryAddress.ToString())
Catch ex As Exception
MessageBox.Show("UnAvailable")
End Try
End Sub
when simple click on button it shows a place . but when i give something input in the textbox and search it, shows
"You seem to be using an unsupported browser. Old browsers can put your security at risk, are slow and don't work with newer Google Maps features. To access Google Maps, you'll need to update to a modern browser."
Any suggestion ? it spoiled my whole day.
thank you
Thank for valuable response... i did like removing some parts..
If TextBox1.Text = String.Empty Then
queryAddress.Append(City)
End If

How do I discover the user's Desktop folder?

I'm making a little application in visual studio which loads a ROM in an emulator.
I have two emulators and 20 ROMs.
I made a form and added a few buttons. When you click the Button it opens a new form and closes the old one. Then on the new form I have four buttons: each one loads a different ROM in an emulator. So when you press Button1 this code is triggered:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles yellow.Click
Shell("C:\Users\shifty\Desktop\pokemon games\Emulator\VBA\VisualBoyAdvance.exe ""C:\Users\shifty\Desktop\pokemon games\Roms\Yellow\Pokemon Yellow.gb""", vbNormalFocus)
End Sub
It works fine - I click it and it loads the game in the emulator. The bit im having trouble with is the file paths. If I send this application to a friend, it would still look for "C:\Users\shifty\Desktop\" - but that's on my computer, not his.
Is there a way to make the application look for the file on his computer (without changing the file path to (C:\Users\""his user name""\Desktop))
Environment.GetFolderPath(Environment.SpecialFolder.Desktop)
This will resolve to be the desktop folder for the current user.
It will even work between XP, vista and Windows 7 properly.
Old post but I have to side with Mc Shifty. You can't assume that everyone is a coding expert. If they were then they wouldn't be here asking questions like that.
None of the answers given above were complete
Environment.GetFolderPath(Environment.SpecialFolder.Desktop)) <<< includes and extra )
Environment.GetFolderPath(Environment.SpecialFolder.Desktop)); <<< extra ) and the ; is C or java not VB which he is obviously using by his example code.
Both of those only give you half of the required code to generate something usable.
Dim s As String = Environment.GetFolderPath(Environment.SpecialFolder.Desktop)
The above code will give you the result needed, c:\users\shifty\desktop
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles yellow.Click
Dim s As String = Environment.GetFolderPath(Environment.SpecialFolder.Desktop)
Shell(s & "\Desktop\pokemon games\Emulator\VBA\VisualBoyAdvance.exe " & s & "\pokemon games\Roms\Yellow\Pokemon Yellow.gb""", vbNormalFocus)
End Sub
There's a mechanism to get the current user's Desktop directory, using Environment.SpecialFolder.
Usage:
Environment.GetFolderPath(Environment.SpecialFolder.Desktop));
I had problems using the Environment.GetFolderPath method from previous answers.
The following works in VB 2012, My.Computer.FileSystem.SpecialDirectories.Desktop
So, if you have a file on a users desktop named "contacts.txt", the following will display the full path,
' Desktop path
Dim desktopPath = My.Computer.FileSystem.SpecialDirectories.Desktop
' Concatenate desktop path and file name
filePath = desktopPath & "/contacts.txt"
MsgBox(filePath)
Documentation
Really old post at this point, but hey, found what I was looking for.
MC SH1FTY, I assume you have figured this out already, but to do what you are trying to do:
1) Call in that code that Spence wrote as a variable (I'd declare it Globally, but that's my preference. To do that:
Public userDesktopLoc As String = Environment.GetFolderPath(Environment.SpecialFolder.Desktop)
2) Either use this DIRECTLY in your code, or make another string to concatenate a directory:
Option A)
Public emulatorPath As String = userDesktopLoc & "pokemon games\Emulator\VBA\VisualBoyAdvance.exe "
Public romPath As String = userDesktopLoc & "pokemon games\Roms\Yellow\Pokemon Yellow.gb"
Then, within your Subroutine, replace your current Shell statement with:
Shell(emulatorPath & romPath, vbNormalFocus)
Or, Option B, which is thedsz's answer:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles yellow.Click
Dim s As String = Environment.GetFolderPath(Environment.SpecialFolder.Desktop)
Shell(s & "\Desktop\pokemon games\Emulator\VBA\VisualBoyAdvance.exe " & s & "\pokemon games\Roms\Yellow\Pokemon Yellow.gb""", vbNormalFocus)
End Sub
By using that you guarantee that the emulator is on the users desktop. This is not always the case. I know I move things around that I download or a friend sends to me. It's better to use App.Path and make sure your emulator.exe is in the directory with your little front end program (usually the case).
the answer is simple.
put this at the top of the form
"Public thepath As String = Environment.GetFolderPath(Environment.SpecialFolder.Desktop)"
that ensures that the file is on their desktop!
then" click on your button or whatever you used to open the emu and type
"Process.Start(thepath + "the emulator.exe "+ "the rom you want")
You need to use a file open dialog to choose your path for the two files. Here is an example.
You then use the two paths in your code:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles yellow.Click
Shell(emulatorPath + "\"" + romPath + "\"", vbNormalFocus)
End Sub

Community server library - issue deleting a user

I have been asked to fix a Community Server forum where thousands of users were created via a script. All of their profile pages are SEOspam for prescription drugs, etc. The forum was not using email verification or admin approval for newly registered users. I turned on the latter for now, but captcha would be nice.
My problem is that it is very cumbersome to mass delete these accounts. I set up a .net grid (Telerik Radgrid actually) so that I could mass select users and click delete. However the following code does not seem to be working (mind the VB nubbery):
Protected Sub rgUsers_NeedDataSource(ByVal source As Object, ByVal e As Telerik.Web.UI.GridNeedDataSourceEventArgs) Handles rgUsers.NeedDataSource
rgUsers.DataSource = Users.GetUsers().Users()
End Sub
Protected Sub btnDelete_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnDelete.Click
For Each item As GridDataItem In rgUsers.SelectedItems
Dim selectedUserID As Integer = item.OwnerTableView.DataKeyValues(item.ItemIndex)("UserID")
Dim userToDelete As CommunityServer.Components.User = Users.GetUser(selectedUserID, False) ' User is definitely populated. '
Dim username As String = userToDelete.Username
Dim deleteStatus As DeleteUserStatus = Users.DeleteUser(User)
Trace.Write(String.Format("Delete result for user {0}: {1}", username, deleteStatus.ToString)) ' Returns enum value 3 (Success.) '
Next
rgUsers.Rebind()
End Sub
The UserDeleteStatus result returns 'Success', however the user is not actually deleted. Am i using the correct delete function? Any help is greatly appreciated, as this is sort of time sensitive (the client is not in the market for penis enlargment pills.)
The issue was that the UserDeleteStatus was actually returning 'AuthenticationRequired'