Understanding the Open method and the Try block in VB.NET - vb.net

I'm using VB.NET for the first time, to check if a file is in use, but there are some lines of code that I don't fully understand.
Can someone explain the two lines of code highlighted below in the comments?
Public Sub Main()
IsFileInUse("C:\someFolder\file.pdf")
End Sub
Function IsFileInUse(filePath As String) As Boolean
IsFileInUse = False
If System.IO.File.Exists(filePath) Then
Dim fileInfo As System.IO.FileInfo
Dim stream As System.IO.FileStream
fileInfo = New System.IO.FileInfo(filePath)
Try
' Can someone explain this line of code?
' how does this determines where to go from here, Catch or Finally?
stream = fileInfo.Open(System.IO.FileMode.Open, System.IO.FileAccess.ReadWrite, System.IO.FileShare.None)
Catch
IsFileInUse = True
MessageBox.Show("It looks like the file is opened")
Finally
If stream IsNot Nothing Then
' What is this closing?
stream.Close()
End If
End Try
Else
MessageBox.Show("File does NOT Exist")
End If
End Function

how does this determines where to go from here, Catch or Finally?
Look at the documentation for FileInfo.Open. The Exceptions section shows all of the possible exceptions that can happen.
If an exception is thrown, the Catch block will be executed.
The Finally block always gets executed, whether or not an exception was thrown.
What is this closing?
It will release the stream's resources, in this case it will close the file.

The Try block runs the code. In the Try block, a stream is used to open the file and access its contents. If that code errors for any reason, it will throw an Exception, which will then cause to the Catch block to be run. The Finally block of the code will run whether an Exception is thrown or not. In the Finally block, the stream to the File is being closed.

The code is determining whether or not the file is currently "in use" by any other processes by attempting to open the file with read/write access. Whether the opening of the file fails or not, it always closes the file stream. It assumes that if opening the file in that mode fails for any reason, then it must be because it is "in use". That's a bad assumption to make, and likely not the best way to accomplish it anyway, but for what it's worth, that's what it's doing.
The Try/Catch block is VB.NET's preferred syntax for exception handling (it replaces the older On Error syntax which predated .NET). When anything inside of the Try section throws an exception, execution will jump to the Catch section. Once execution of the Catch section completes, it then jumps to the Finally section. If nothing in the Try section throws an exception, then once it's done, it also jumps to the Finally section. Essentially, everything in the Finally section is "guaranteed" to execute, whether or not an exception occurred, whereas the code in the Catch section only executes when there is an exception.
In other words, consider this example:
' Outputs "ABCE" (does not output "D")
Console.Write("A")
Try
Console.Write("B")
Console.Write("C")
Catch
Console.Write("D")
Finally
Console.Write("E")
And compare it to this example:
' Outputs "ABDE" (does not output "C")
Console.Write("A")
Try
Console.Write("B")
Throw New Exception()
Console.Write("C")
Catch
Console.Write("D")
Finally
Console.Write("E")
See the MSDN article for much more information on the topic.

Related

How to write 'if not caught' code in a Try Catch

Wondering if the following can be done in a simple way:
Try
Some Statements
Catch ex As ...
Error handling stuff
NotCatch
Code to handle *only* if there was no Catch
End Try
A Finally bloc will not do it, because it is executed even if the Catch was executed. Putting the code after the End Try doesn't work either, as it's always executed. I tried to place an Exit Try after the Error handling stuff, but then nothing is executed any more before the End Try.
Is there an clean and easy way to do this without variables to remember that the Catch was executed?
The normal way is like this:
Try
Some Statements
Code to handle *only* if there was no Catch
Catch ex As ...
Error handling stuff
End Try
This works because as soon as an exception is thrown, control jumps to the catch block and the rest of the try block is ignored. Or to put it another way: If a line in the "try" runs, then you know there hasn't been an exception yet.
If you have other requirements that means this wont work then you'll need to provide more information.

thread pool error trapping

Checking on a best practice here.
I am calling a ThreadPool to run an Async process, specifically sending an SSL email with an attachment which seems to take a good long while.
This is just test code, I thought I would drop this in a Try Catch just incase something failed. But will the thread ever even come back here? I have tested this closing the web page, the browser, clicking the back button on the page. The email always makes it through.
Try
System.Threading.ThreadPool.QueueUserWorkItem(AddressOf DoAsyncWork) '
Catch ex As Exception
Throw ex
Exit Sub
End Try
I am not trying to force a failure, yet I guess, but I would like to know how best to trap if the thread fails.
Protected Sub DoAsyncWork(ByVal state As Object)
Dim oMyObject As New sendSSLemail
oMyObject.SSL(userName, , strMessageBody, emailAdd, , permFileLocation, , "CodeMsg")
End Sub
A more convenient way of doing work with the thread pool is to use Task.Factory.StartNew(Action). It returns a Task object which can be Awaited or blocked on with Wait.
Once the task completes, the Exception property of the Task can be used to determine whether an exception was thrown and unhandled by the task's subroutine. (If it's not Nothing, then the InnerException property has the real exception that was thrown.)
Dim task = Task.Factory.StartNew(AddressOf WorkFunction)
' do stuff that doesn't depend on WorkFunction having completed
task.Wait()
If task.Exception IsNot Nothing Then Throw task.Exception.InnerException
After a Throw, the sub is exited anyway (the call stack is unwound looking for a Catch), so the Exit Sub statement does nothing. Wrapping a QueueUserWorkItem call in a try block also does nothing, because any exception would occur on the other thread. You would only get exceptions thrown immediately by QueueUserWorkItem, which off the top of my head only includes complaints about the delegate being Nothing.
Asynchronous tasks can also return values. For more information on that, see the TaskFactory methods that return a Func(Of Task).

Unable to delete all files from temporary folders in vb.net

I am using the following code to delete all files from a particular folder:
Sub DeleteFiles(Folder As String)
If Directory.Exists(Folder) Then
For Each _file As String In Directory.GetFiles(Folder)
File.Delete(_file)
Next
For Each _folder As String In Directory.GetDirectories(Folder)
DeleteFiles(_folder)
Next
End If
End Sub
Whenever I use the above code to delete all files from "C:\Temp" by calling it using DeleteFiles("C:\Temp"), It deletes all the files successfully, but whenever I try to use the same code for deleting files in "C:\Windows\TEMP\", it breaks the operation saying that the file is in use. I want that the code should not raise an exception and stop deleting the files right-away. If the file cannot be deleted, the code should move on to the next file and try deleting it. This way, it should be able to delete maximum possible files from that directory.
You need to handle exceptions raised by File.Delete() using a Try....Catch... statement. I'm not a VB coder (I'm surprised to find myself answering this question), but something like this should work:
Sub DeleteFiles(Folder As String)
If Directory.Exists(Folder) Then
For Each _file As String In Directory.GetFiles(Folder)
Try
File.Delete(_file)
Catch e As System.IO.IOException
Console.WriteLine(e.Message)
End Try
Next
For Each _folder As String In Directory.GetDirectories(Folder)
DeleteFiles(_folder)
Next
End If
End Sub
This will catch an System.IO.IOException exception, log that it was received, and then ignore it. Note that this will catch a number of other File.Delete() related exceptions such as System.IO.DirectoryNotFoundException, System.IO.PathTooLongException, etc. If you want to catch these, you must add a Catch clause for each before the more general System.IO.IOException. The possible exceptions are listed here, along with an example of using File.Delete() - you just need to read the docs.
You might like to also look at Directory.Delete to recursively delete a directory, its files, and its subdirectories.
You can't stop an exception being thrown. What you need to do is catch the exception, process it as appropriate (which may mean just ignoring it) and move on. That means putting a Try...Catch block inside your first loop. That way, when File.Delete throws an exception, you can catch it, ignore it and the loop will continue.
Be sure to catch only the type of exception that you expect to be thrown though. Otherwise, something completely unexpected may be causing an issue and you're just ignoring it, which is bad. Only ignore exceptions that you reasonably expect and know can be safely ignored.
Dim temp As String = Environment.GetEnvironmentVariable("TEMP")
Dim k As String() = System.IO.Directory.GetFiles(temp)
Dim i As Integer
For i = 0 To k.Length
On Error Resume Next
Kill(k(i))
System.IO.File.Delete(k(i))
Next

Repeated error handling

So in my vb.net application, i've got alot of try and catch blocks for error handling, especially whenever my app talks to the db.
i'm running through a series of if/elseif statements to see if
ex.tostring.contains("Unable to connect to any of the specified MySQL hosts")
and various bits like that.
At the minute, I wrote this out and copy and pasted it into each catch, but I know there will be a much more efficient way to do this whereby the code is just in one place and called as and when required.
I tried to implement it as a function, but I had trouble passing info to the function.
So i thought I'd ask and see how you guys go about doing this?
You don't need multipe try...catch statements for a program. One is enough.
If i understood you correctly, you want to print or show the error that occured inside the Try block.
Public Sub main()
Try
'Do something
Catch ex As Exception
End Try
Try
'Do something else
Catch ex As Exception
End Try
If ex.tostring.contains("something") than
End Sub
Instead you can do something like this:
Public Sub main()
Try
'Do all your code here.
Catch ex As Exception
MsgBox(ex.ToString)
End Try
End Sub
In this part, the compiler will automaticlly print the error occured in the program.
You can perform some action based on the type of exception thrown. Checking the text if not recommended as this could change with a new version of .net or mysqldata
Try something like this:
Try
'
' Programming lines of code
'
Catch exError As MySqlException
' an error occurred with MySql
Catch e As Exception
' a General error occurred
Finally
' Cleanup custom and unmanaged resources if necessary
End Try
Have a look at the MySQL Documentation for their recommendations

Is there a better way to get visual studio to ignore try/catch in debug mode

I want the designer to catch the error when I am debugging and I want the user to see my friendly message if an error occurs for them. I know I can acomplish this with the following:
#If Debug=False Then
Try
#End If
'some code here
#If Debug=False Then
Catch ex as exception
Messagebox.Show("Errors suck")
End Try
#End If
I do not want to have to write all the #statements and having them cluttering up my code. It seems like this should be a common need and there has to be a better way. Does anyone know a better way?
In VS.NET you can say whether you want the debugger to break when an exception is thrown (not just when it's unhandled).
Look on the Debug | Exceptions... menu item (Ctl-Alt-E on my keyboard shortcuts). Pick the excepption you're interested in, then tick the "thrown" box for that exception.
You can tick that box at several levels (all CLR exceptions, all CLR exceptions in a given namespace, or very specific exceptions)
There is no good way to get it to ignore a try catch other than what you've done. But you can make the code a little bit cleaner and essentially get the same effect. You essentially are trying to prevent the action in the catch block from running. A better way to do that is a conditionally compiled method.
Try
...
Catch ex As Exception
DebugLog(ex)
Throw
End Try
<Condition("DEBUG)> _
Public Sub DebugLog(ByVal ex As Exception)
Messagebox.Show("errors suck")
End Sub
In the catch section of your Try..Catch you should write the exception message, stacktrace, and anything else you may want to a log file -- additionally you could write that data to the Windows Event log as well.
At worst, you could just put break-points in the Catch section of your Try..Catch blocks, since you shouldn't normally hit them it should'nt be a big deal once setup.
Here is how I do it:
Enabled:
Try ' : Catch: End Try
doSomething
andSomeMore
etcEtc
' Try
Catch ex As Exception
handleException
End Try
Disable the above by deleting the two comment characters:
Try : Catch : End Try
doSomething
andSomeMore
etcEtc
Try
Catch ex As Exception
handleException
End Try