Is there a way to get the last thrown exception outside of a try/catch block? - vb.net

Edit:
To all answerers and commenters: Please focus on providing the solution I request rather than offer ways to refactor it. The code provided below is a very condensed example for the sake of brevity. I've already stated below that this type of code exists in 20 or 30 places throughout the app and that I am choosing not to move/merge/refactor any of that code if a simpler solution exists.
Original Question:
First, here's brief run-down: We have an app that was developed by an offshore team. The purpose of this application is to run nightly maintenance on various database tables. It is a WinForms app, but it acts more like a console app as all it does is 1) execute a single method in Form1_Load and then 2) call End to shut down the program.
The problem is that the error email notification doesn't work, so I have been charged with the task of fixing it. Consider this code:
Try
'This inner Try/Catch is actually code in another method
Try
'Run some code here
Catch ex As Exception
'Errors are logged silently to text file here
End Try
Catch ex As Exception
'Code to email exception details is here
End Try
The problem is that an exception is thrown and handled in the inner Try/Catch. Because of this, there's no exception to be handled in the outer Try/Catch, hence why no email notification is being sent.
Someone might say to just add Throw ex in the inner Catch, but keep in mind that there are about 20 or 30 places in the code where exceptions are handled like this. The decision I am making is to just get it working for now and not undergo that kind of development effort. Therefore, I seek a way to somehow acquire the last exception thrown by the application. This way, I can add a Finally block to the outer Try/Catch and do something like this:
Finally
If Not Application.GetLastException() is Nothing Then
SendErrorEmail(Application.GetLastException())
End If
End Try

So if I understand this correctly, your application catches all exceptions and logs them silently to a file.
You want to change the behavior so that when the program ends you get the last exception thrown, if any, and send an email with that exception detail. But the last exception thrown isn't stored anywhere.
And you want to change this behavior without modifying the code that handles the exceptions.
That can't be done. How do you expect to change the program's behavior without changing the program's behavior? What you ask is impossible. (And, no, not even Yoda would be able to pull this particular X-wing out of the swamp.)
There is no runtime property that automatically saves the last exception thrown.
You will have to make some modification to the code that catches the exceptions. You say that the code takes this general format:
Try
'This inner Try/Catch is actually code in another method
Try
'Run some code here
Catch ex As Exception
'Errors are logged silently to text file here
End Try
Catch ex As Exception
'Code to email exception details is here
End Try
I take it that the problem is in the inner Catch block. Seems to me that if there's common code to log the errors to a text file, that code should be in a separate method. If it is, then modify that method to save the last exception in a property that can be accessed by your GetLastException method. If there isn't a common method that handles the exception logging then you'll have to make the change at every place.
The commenters are correct: A general "catch all exceptions" is almost always a bad idea. Especially when the "handling" consists of logging and continuing. When you catch some random exception, you have no idea what the state of your program is. It's very likely that the data is corrupt and the program's state is unstable. "Log and continue" just makes the problem worse, and can lead to all kinds of interesting side effects like data corruption, infinite loops, deadlock, etc.
Your best course of action here is to refactor the code. Actually, the best course would be to send it back to the offshore developers and tell them to do it right. But that's probably too much to ask.

I'm quite late to this party but you could try this rather ugly way of doing things.
Firstly extend the Application class by adding a LastException property and a GetLastException function, see here for details.
Secondly add a line to each of the inner Catch blocks and set the LastExcepotion property:
Application.LastException = ex
There you go, no need to refactor all that offshore code.

Related

How do I find out what called my shared function

I have a function in vb.net that is shared. At one point it throws an error that says an 'open datareader already exists'. But this function is called from several different places in the program. How can I find out which part of the program called the function when it errors out?
You go to the Debug menu, show the Exceptions window, put a tick next to CLR exceptions and then run your program until it errors. As soon as the exception is raised VS will break, you will be able to see the call stack, and find out where the code was before. Note that this causes VS to stop on every exception, handled or not; it can become tedious to get to where you want to be - untick the "always break when this type of exception is thrown" in the exception helper if you just keep getting irrelevant exceptions breaking before this error you're trying to chase
It sounds like you're perhaps not creating/disposing of your DB access resources properly, especially if this is a static/shared context. Are you trying to reuse one DB connection? It wouldn't hurt to post the code of the faulting module

Handling pgPL/SQL exceptions From QtSQL

Short and simple:
How to catch pgPL/SQL exceptions with QtSQL?
I haven't found any example or info at the docs.
More details:
I'm developing the front end for a system with Qt 5.3. The database perform some validation at some of the inputs and raise custom exceptions when something is invalid. What I want is to be able to handle these exceptions at he front end code, showing appropriate messages to the user.
EDIT:
I have tried to use the QSqlError class. Although it gave me the exception, it gave me too much data which will need to be parsed to be useful. Is there a way to get the exception raised without parsing the messages?

Better way to Handle error

I recently migrated a VB6 app to VB.Net. Entire VB6 dependency are removed . And the code was working fine just for a single module mean to say like for WinApp it is working fine.
Now my requirement has been changed, now the same class will be accessed by multiple application , it might a Windows App, Web App or a web service. So I am not able decide any efficient error handling pattern.
So you you guys help me out. Currently what I am doing is that parent function , i am passing two vars LogError as bool and ErrorMessage as string parameter, that will further check something like this
Catch(ex as Exception)
If LogError then
MessageBox.Show("My_Module_Name :" & ex.Message)
EndIf
ErrorMessage = ex.Message
End Try
Also same catch block is used in all other functions/ subroutines.
So what I need is any elegant handling method that will work efficiently on cross-app platform(win/web/service)
I'd suggest logging the messages, either to a log file or to the Event log, but why not let the clients choose, in that you could add some methods to let the client decide where it should be logged. Though instead of having your exception handler handle the message and put it into an errormessage variable I'd just follow the logging with a throw so that the Exception continued up in the call chain until some code that knew how to handle it got it.
In general it's not good practice to catch Exception, you should catch only the exceptions that you can handle. But I think it's ok if you just want to log it and then will re-throw it again.

Get Rid of Error Message - VB.NET

When I do the try/catch method in my vb.net project I will try the code I want and when it can't do it, i make a message box right after the catch method. The thing is that it will show the message box, and then another message from the program itself. Like for example, I have here a MySQLException, and when i click ok on the message box, it will show another one right after showing the exception itself. How would I be able to get rid of this so the user doesn't have to see this, and the program can continue.
Thanks,
kevin
It sounds like you're actually getting more than one exception. Have you checked the stack traces for both errors?
What I think is happening is that your first function is throwing the MySQLException and then returning nothing. You're then probably getting a NullReferenceException from whatever made the call to the database.
Your best bet is to not catch some many exceptions. Your data layer should be free of Try/Catch blocks unless you're trying to cater for something very specific. Your business layer should then catch any other non-general exceptions that occur specific to the functionality there. Finally, your application layer should be handling all of your general exceptions and reporting on them from there.
Try this. It should only display one message. Make sure your original message is coming from a statement after the Try.
Try
code
Catch ex as exception
call msgbox (ex.message)
end try

A recursive way to display Exception Messages in ASP.NET

I have started to make heavy use of exceptions, I'm sure I'll grow out of it as a learn the advantages and disadvantages the hard way, but until I've become an exception guru I'd like to know if this technique is acceptable.
I intend to wrap, say a database exception in my own 'SorryFailedToSaveYourData' exception and then recursively moved through the exception displaying the messages, kinda like this:
Try
DoSomeWork
Catch
BuildErrorMessage(lblError,ex)
End Try
Public Sub BuildErrorMessage(ByVal lbl As Label, ByVal ex As Exception)
lbl.Text += "<br />" & ex.Message
While Not ex.InnerException Is Nothing
BuildErrorMessage(lbl, ex.InnerException)
End While
End Sub
Is this practice useful or I have I completely missed the boat when it comes to handling exceptions? I know you can create your own exceptions but it seems like overkill for the size of the projects we are working on.
Thanks
I wouldn't display each and every inner exception message to the user of your application. I would catch the real exception (ie SqlException) and rethrow it as your own exception (ie throw new YouCantSaveThisTwiceException("This customer ID already exists") ). Then just display that hand typed message to the user on a nice pretty display screen. Send yourself an email / log file / etc with the full-on stack trace.
This serves two purposes:
1) You get to see the real stack trace which makes it easier for you to find and fix the problem.
2) The users do not have to be shown a big scary stack trace. Instead, they read a nice message written by you which reassures them that although there is a problem, they did not "break" the application.
This works well for exceptions which you don't expect a user to be able to fix with different input. For exceptions which validate user input, often you can catch those in the presentation layer and display your nice message back to them on a label without leaving the form.
Only (ONLY!!!) use this technique if you know exactly what you are going to be catching and you give the users clear instruction on how to fix it. Otherwise, you end up with the worst of both worlds. The users don't know what to do, and you are not alerted of the presence of a bug. Never wrap an entire method in a try-catch simply to "catch all" exceptions. That type of handling should be done globally at the application level.
I do all of my global exception handling (emailing, logging, etc) in the application_error handler method within Global.asax. You could also create an HttpModule which handles application errors. Then you can carry that functionality with you from project to project.
ex.ToString() will build the exception text formatted, you should use that rather than the .Message as it might not give you the full information you will need for debugging.
I would also recommend passing a stringbuilder down the recursion instead of a label using AppendLine(), this way you can also use that text to send email notifications, write the event viewer, as well as a log file. For displaying in your UI (it looks like you want html) simply set the labels text value to
StringBuilder.ToString().Replace(Environment.NewLine, "<br />")
You're building a label inside of an exception, presumably because you want to display the message to the user. If your exception spans more than one tier of the application (you mentioned wrapping your own data exception), then this is a terrible idea as it will violate encapsulation and force your exception handling to be using UI elements.
Generally, though, you'll want to not display error messages to the user. What does a user care that a stack overflow happened? He only cares that the application is broken and that an error report was logged and sent to the appropriate team.
Generally you want to have exceptions if and only if the application is in a state in which it can no longer run. If it's something that just happens conditionally you'll want to handle it explicitly with conditions to check for it rather than using the exception mechanism.
For example, if you know users will be connecting from home and you can't guarantee there will be an Internet connection, you check for an Internet connection and display a message saying the user needs to connect, instead of just trying to use an Internet connection and creating an exception if none exists.
Edit
I misread your question at first, you probally don't want to do this if your displaying the information to the end user. You will want to do what I am suggesting if your going to log the exception for you to troubleshoot latter.
====
This is standard although I would also capture the stack trace and any items in the Data property (Although I've not seen any framework code use this you never know and its useful if your going throw your own exceptions or rethrow an exception.
Although your actual code has an error in it your probally end up in an infinite loop since your outer exception will always have an inner exception.
Public Sub BuildErrorMessage(ByVal lbl As Label, ByVal ex As Exception)
lbl.Text += "<br />" & ex.Message
If Not ex.InnerException Is Nothing Then
BuildErrorMessage(lbl, ex.InnerException)
End If
End Sub