VB.net - see if remote file exists - vb.net

I have a function to check if a remote file exists after being passed the URL. Assuming it doesn't exist the function would return 0 to be used in another sub. Here's what I have:
Public Function RemoteFileExists(ByVal fileurl As String) As Integer
Dim request As FtpWebRequest = DirectCast(WebRequest.Create(fileurl), FtpWebRequest)
request.Method = WebRequestMethods.Ftp.GetFileSize
Dim response As FtpWebResponse = DirectCast(request.GetResponse(), FtpWebResponse)
If response.StatusCode = FtpStatusCode.ActionNotTakenFileUnavailable Then
RemoteFileExists = 0
Exit Function
End If
Dim fileSize As Long = response.ContentLength
MsgBox(fileSize)
If fileSize > 0 Then
RemoteFileExists = 1
Else
RemoteFileExists = 0
End If
End Function
When I run the app and purposely supply a URL that doesn't exist Visual Studio gives me System.Net.WebException was unhandled. Message=The remote server returned an error: (550) File unavailable (e.g., file not found, no access).
I assumed that the "if response.StatusCode..." would handle that rather than shutting down the program.
Any help appreciated.
DWM

First of all you should switch from Integer to Boolean since you only return either 1 or 0 anyway. A Boolean can be either True or False.
Secondly, you should wrap everything in a Try/Catch block to handle any error that might occur. Wrapping code in Try/Catch can catch most errors (except for the most extreme ones) and putting it around code that could throw an error saves you from having your application crash for the more simple errors.
And finally, you should use Return <value> instead of RemoteFileExists = <value>, since Return will both return the wanted value AND exit the function.
Example implementation:
Public Function RemoteFileExists(ByVal fileurl As String) As Boolean
Try
Dim request As FtpWebRequest = DirectCast(WebRequest.Create(fileurl), FtpWebRequest)
request.Method = WebRequestMethods.Ftp.GetFileSize
Dim response As FtpWebResponse = DirectCast(request.GetResponse(), FtpWebResponse)
If response.StatusCode = FtpStatusCode.ActionNotTakenFileUnavailable Then
Return False 'Return instead of Exit Function
End If
Dim fileSize As Long = response.ContentLength
MsgBox(fileSize)
If fileSize > 0 Then
Return True
Else
Return False
End If
Catch ex As Exception 'Catch all errors
'Log the error if you'd like, you can find the error message and location in "ex.Message" and "ex.StackTrace".
MessageBox.Show("An error occurred:" & Environment.NewLine & ex.Message & Environment.NewLine & ex.StackTrace, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
Return False 'Return False since the checking failed.
End Try
End Function
In the Catch block, ex.Message is the error message, and ex.StackTrace is where in the code the error occurred.

Related

Getting "The underlying connection was closed: An unexpected error occurred on a receive." on FTPWebResponse.close()

I have a VB.Net function that will check if the FTP directory exists, otherwise create the directory.
The function works fine at first, but when the number of files in the FTP directory has reached a certain limit, response.close() in the finally block throws an exception : System.Net.WebException:The underlying connection was closed: An unexpected error occurred on a receive..
my function
Public Function funFTPCheckFolder(ByVal ftpPath As String, Optional ByVal bCreate As Boolean = False) As Boolean
Dim request As FtpWebRequest = Nothing
Dim response As FtpWebResponse = Nothing
Dim strReader As StreamReader = Nothing
Try
request = WebRequest.Create(ftpPath)
With request
.Credentials = New NetworkCredential(_username, _password)
.Method = WebRequestMethods.Ftp.ListDirectory
.KeepAlive = False
'.UsePassive = True
End With
response = CType(request.GetResponse, FtpWebResponse)
Catch ex As Exception
funFTPCheckFolder = False
If (bCreate = True) Then
request = WebRequest.Create(ftpPath)
With request
.Credentials = New NetworkCredential(_username, _password)
.Method = WebRequestMethods.Ftp.MakeDirectory
' .KeepAlive = False
.UsePassive = True
End With
response = CType(request.GetResponse, FtpWebResponse)
funFTPCheckFolder = True
End If
Exit Function
Finally
If response IsNot Nothing Then
response.Close()
response = Nothing
End If
If request IsNot Nothing Then
request.Abort()
End If
End Try
Return True
End Function
In this case, when the file amount in the FTP directory reached 481, an exception is thrown.
exception message
After moving one file to the subdirectory, it works fine again, so it seems to be a problem with the amount of file in the directory.
For now the only way I can come up with is wrap it with try/catch, but not sure will it cause any other error.
Try
If response IsNot Nothing Then
response.Close()
End If
Catch ex As Exception
End Try
I want to find out what exactly cause the problem, any thoughts would be appreciated!

SSIS Script Task supress onerror

I have a script task which downloads a file using a HTTP connection object. This script task is part of a package which is called by another package. Sometimes the connection cannot be established. In these instances I want to retry the connection a number of times before finally raising an error if the connection attempts fail.
I tried to implement this. It appeared to work and the task does not fail. However an OnError event is still propagated every time an exception happens in the script task even though the script task doesn't fail. The fail occurs once control is passed from the child package back to the parent package.
Public Sub Main()
Dim tryTimes As Integer = 0
Dim maxTimes As Integer = 4
While (True)
Try
Dim nativeObject As Object = Dts.Connections("HTTP Connection Manager").AcquireConnection(Nothing)
'Create a new HTTP client connection
Dim connection As New HttpClientConnection(nativeObject)
Dim filename As String = Dts.Variables("Working_File").Value
connection.DownloadFile(filename, True)
Dts.TaskResult = ScriptResults.Success
Exit While
Catch ex As Exception
If (tryTimes < maxTimes) Then
tryTimes = tryTimes + 1
Thread.Sleep(30000)
Else
MsgBox(ex.Message)
Dts.TaskResult = ScriptResults.Failure
Throw
End If
End Try
End While
End Sub
I am hoping to get a solution where the OnError event is not called unless the connection attempts fails a certain number of times.
Try writing the same code an Fire a Warning on first 4 trial and on the 5th trial fire an error, i am not sure if it will works:
Public Sub Main()
Dim tryTimes As Integer = 0
Dim maxTimes As Integer = 4
While (True)
Try
Dim nativeObject As Object = Dts.Connections("HTTP Connection Manager").AcquireConnection(Nothing)
'Create a new HTTP client connection
Dim connection As New HttpClientConnection(nativeObject)
Dim filename As String = Dts.Variables("Working_File").Value
connection.DownloadFile(filename, True)
Dts.TaskResult = ScriptResults.Success
Exit While
Catch ex As Exception
If (tryTimes < maxTimes) Then
tryTimes = tryTimes + 1
Dts.Events.FireWarning(0, "Error ignored", _
"Retrying in 30 seconds", String.Empty, 0)
Thread.Sleep(30000)
Else
Dts.Events.FireError(-1, "", "Error message: " & ex2.ToString(), "", 0)
Dts.TaskResult = ScriptResults.Failure
End If
End Try
End While
End Sub
Reference
How to suppress OnError event for a specific error in a Script task (SSIS 2005)
You'll want to use a label, outside the try, and a GoTo within your catch
Public Sub Main()
Dim tryTimes As Integer = 0
Dim maxTimes As Integer = 4
RunCode: 'Label here
While (True)
Try
'your code here
Exit While
Catch ex As Exception
If (tryTimes < maxTimes) Then
tryTimes = tryTimes + 1
Thread.Sleep(30000)
GoTo RunCode 'after we catch the exception and eval tryTimes go back and retry
Else
'MsgBox(ex.Message)
Dts.Events.FireError(-1, "", "Error message: " & ex.ToString(), "", 0)
Dts.TaskResult = ScriptResults.Failure
'Throw
End If
End Try
End While
End Sub

The underlying connection was closed thrown in 40th iteration of VB.Net application

This question appears multiple times on StackExchange but I just can't solve it. Most answers say that this arises due to SSL or TLS issues and to set the protocol to TLS10 or to use KeepAlive.
In my case, I am calling my own PHP endpoint and not using SSL. The server is hosted on GoDaddy.
I am retrieving records from the server. Due to the large size of the returned data, I placed the calls in a loop. The loop runs and fetches data for 40-50 iterations before throwing this error. It is not a timeout issue as the error is thrown within milliseconds.
I suspect a stream or connection is not closing and the VB.Net program is running out of resources or the server has too many open connections.
The code below is slightly abridged to remove sensitive info:
While True
' Create the request
uri = New Uri(My.Settings.ServerURL & My.Settings.GetEmployeeRecords)
request = DirectCast(WebRequest.Create(uri), HttpWebRequest)
' Add user credentials
creds = New CredentialCache
creds.Add(uri, "Basic", New NetworkCredential(My.Settings.UserId, My.Settings.Password))
With request
.Method = "POST"
.ContentType = "application/x-www-form-urlencoded"
.AutomaticDecompression = DecompressionMethods.GZip + DecompressionMethods.Deflate
.Credentials = creds
.KeepAlive = False
.ProtocolVersion = HttpVersion.Version10
.ConnectionGroupName = Guid.NewGuid().ToString()
.UserAgent = "VB.NET App"
.AllowAutoRedirect = False
End With
' Add parameters
strPostData = String.Format("offset={0}&limit={1}", iOffset, iLimit)
request.ContentLength = strPostData.Length
Try
Using sw As New StreamWriter(request.GetRequestStream)
sw.Write(strPostData)
sw.Close()
End Using
Catch ex As Exception
e.Result = "Error Setting Request Data"
Exit Sub
End Try
' Send the request to the server
Try
response = DirectCast(request.GetResponse, HttpWebResponse)
Catch ex As WebException
e.Result = "Error Sending Request" **<-- This is where it is thrown**
Exit Sub
End Try
' Open the response
Try
reader = New StreamReader(response.GetResponseStream)
Catch ex As Exception
e.Result = "Error Reading Request"
Exit Sub
End Try
' Read the full response
rawresp = reader.ReadToEnd()
reader.Close()
response.Close()
' We should never get a blank response
If rawresp = "" Or rawresp = "[]" Then
e.Result = "Blank Response"
Exit Sub
End If
' The response should be in JSON. Parse it
Try
jResults = Linq.JObject.Parse(rawresp)
Catch ex As Exception
e.Result = "Error parsing response"
Exit Sub
End Try
' Get the complete response into jResults
' The jResults would contain {statuscode, statusDescription, data[]} where the data element would be an array of employees
' Check for error returned in response JSON
If jResults("statusCode").ToString = "404" Then
Exit While
End If
If jResults("statusCode").ToString <> "0" Then
e.Result = "Error received from server"
Exit Sub
End If
' Get the array for the employee records
Try
jEmployees = Linq.JArray.Parse(jResults("data").ToString)
Catch ex As Exception
e.Result = "Response Does Not Contain Employee Array"
Exit Sub
End Try
' Everything is fine. Add the recordds to the local database
SaveEmployeesToLocalDB(jEmployees)
iCount = jEmployees.Count
iOffset += iCount
iTotalRecords += iCount
If iCount = 0 Then
Exit While
End If
If iTotalRecords Mod (20 * iLimit) = 0 Then
Application.DoEvents()
Threading.Thread.Sleep(3000)
End If
End While

Object variable or With block variable not set?

I get this error when i run my program:
A first chance exception of type 'System.NullReferenceException' occurred in Microsoft.VisualBasic.dll
Object variable or with block variable not set
Here is my code:
Dim rt As String = ""
Dim out As String
Dim wRequest As WebRequest
Dim wResponse As WebResponse
Dim SR As StreamReader
Dim time As Date
time = Now()
Try
wRequest = WebRequest.Create(Address)
wRequest.Timeout = 10000
wResponse = wRequest.GetResponse
SR = New StreamReader(wResponse.GetResponseStream)
rt = SR.ReadToEnd
SR.Close()
Catch wex As WebException
Dim status As WebExceptionStatus = wex.Status
If status = WebExceptionStatus.Timeout Then
MessageBox.Show("Could not establish a connection to the selected exchange server.", "Connection Timed Out", MessageBoxButtons.OK, MessageBoxIcon.Warning)
ElseIf status = WebExceptionStatus.ConnectFailure Then
MessageBox.Show("Could not establish a connection to the selected exchange server.", "Connection Failed", MessageBoxButtons.OK, MessageBoxIcon.Warning)
ElseIf status = WebExceptionStatus.ProtocolError Then
MessageBox.Show("Could not establish a connection to the selected exchange server.", "Connection Protocol Error", MessageBoxButtons.OK, MessageBoxIcon.Warning)
End If
End Try
The source of your error could be your Address variable.
Please try prefix with http:// in front.
Example:
Address = "http://www.google.com"
for more further information, please read MSDN WebRequest.Create Method (String)
The problem is most likely that wResponse.GetResponseStream is failing because wResponse is null. (which is probably because your Address variable isn't valid).
Try adding
Catch ex As Exception
MessageBox.Show("Some other error occurred: " + ex.Message, MessageBoxButtons.OK, MessageBoxIcon.Warning)
End Try
after your WebException Catch block to see what the problem is.
Or just put a breakpoint on SR = New StreamReader(wResponse.GetResponseStream) and look at wResponse (your choice).
I am checking your code and it works fine.
Here's a demo although I made a little change on the declaration of time variable and putting a string on WebRequest.Create() like:
Dim time As Date = Now
and
WebRequest.Create("https://www.google.fm")
And as per my own search there is nothing much to be concerned about with this kind of error, see the link below.
A first chance exception

Timeoutexception on TCP not handled

I took this code from a website since VS 2010 doesn't support the timeout for the TCP connections:
Private Function ConnectWithTimeout() As Boolean
Dim ar As IAsyncResult = TCPClient.BeginConnect(IPAddress, TCPPort, Nothing, Nothing)
Dim wh As System.Threading.WaitHandle = ar.AsyncWaitHandle
Try
If Not ar.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(2), False) Then
TCPClient.Close()
TCPClient = New System.Net.Sockets.TcpClient
Throw New TimeoutException()
End If
Catch ex As Exception
ThrowError("Timeout on connecting to " & IPAddress & " at port " & TCPPort & ".")
Return False
Finally
wh.Close()
End Try
Return True
End Function
And it works fine, but everytime, it gives me this on the debug output:
"A first chance exception of type 'System.TimeoutException' occurred in"
Even if I'm catching all the exceptions. Is there a way to get rid of this exception message as it is handled?
I've tried this:
Dim connectDone As New System.Threading.AutoResetEvent(False)
TCPClient.BeginConnect(IPAddress, TCPPort, New AsyncCallback(Sub(ar As IAsyncResult)
TCPClient.EndConnect(ar)
connectDone.Set()
End Sub), TCPClient)
'client.BeginConnect("127.0.0.1", 80, new AsyncCallback(delegate( IAsyncResult ar ) { client.EndConnect( ar ); connectDone.Set(); }), client);
If Not connectDone.WaitOne(2000) Then
Debug.WriteLine("TIMEOUT")
Return False
End If
Return True
But it gives me InvalidOperationException on the beginconnect line:
BeginConnect cannot be called while another asynchronous operation is in progress on the same Socket.
Private Function ConnectWithTimeout() As Boolean
Dim ar As IAsyncResult
Dim wh As System.Threading.WaitHandle
Try
ar = TCPClient.BeginConnect(IPAddress, TCPPort, Nothing, Nothing)
wh = ar.AsyncWaitHandle
Cath ex as Exception
'Code to catch exception
End Try
Try
If Not ar.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(2), False) Then
TCPClient.Close()
TCPClient = New System.Net.Sockets.TcpClient
Throw New TimeoutException()
End If
Catch ex As Exception
ThrowError("Timeout on connecting to " & IPAddress & " at port " & TCPPort & ".")
Return False
Finally
wh.Close()
End Try
Return True
End Function