Related
I have a couple of questions around exception management for a website:
in the catch block can I have a static class with a handle exception method that handles the exception like so:
catch (Exception ex)
{
throw ExceptionHandler.HandleException(...);
}
where ExceptionHandler.HandleException is a static method that returns a variable of type System.Exception. Is this a good practice? Any possible problems with this approach? Will it be thread safe?
In my application I have a DAL layer that is called by the Business layer and the Business layer is called by the UI. So, is it a good practice to just re-throw all Custom exceptions so they bubble up right up to the UI where they get displayed whereas System.Exception types get logged and I throw a custom exception in the catch block?
for eg in DAL and Business Layer like so:
catch (CustomExceptionBase ex)
{
throw;
}
catch (Exception sysEx)
{
ICustomExceptionBase ex = new SysException(sysEx);
ex.Handle();
throw BusinessException("Some problem while serving your request");
}
In the UI layer like so
catch (CustomExceptionBase ex)
{
//when custom exception bubbles up; code to display text to user on screen
}
catch (Exception sysEx)
{
ICustomExceptionBase ex = new SysException(sysEx);
ex.Handle();
//display error on screen;
}
Here CustomExceptionBase implements ICustomExceptionBase and inherits Exception. SysException & BusinessException both inherit from CustomExceptionBase.
Thanks for your time...
EDIT
The intent of rethrowing in the system.Exceptions block is so that if there is a fatal error like database connection lost or something similar then I log it for the technical helpdesk and return a ticket number and rethrow the same so the user knows that something went wrong and this is your reference number to follow up. For all custom exceptions in the DAL layer or Business layer, I just bubble it up all the way to the UI where the text gets displayed.
I suspect some of the answers at least are entirely down to your architecture. In the first case it all depends on what ExceptionHandler.HandleException does exactly. Does it generate a new exception based on some criteria or is it just going to return the original exception?
Whether its thread-safe or not entirely depends on its implementation. For example in the following trivial case I'd say it was thread safe:
public static Exception ExceptionHandler.HandleException(Exception ex)
{
return ex;
}
In other cases it could easily be not thread safe. eg:
public static string message;
public static Exception ExceptionHandler.HandleException(Exception ex)
{
message = ex.ToString;
sleep(2000);
return new Exception(message);
}
The latter example clearly has scope for the message variable to be changed by another thread while this one is asleep.
As for the second... Exceptions should be handled where it makes sense to handle them. There is no hard and fast rule. If some part of the code can effect a recovery from an exception (or is willing to skip over it) then catch it at that point and not earlier. If an exception is truly fatal then nothing should be trying to catch it and pretend otherwise so you should just let it bubble right up to the top and do something like alert your user that things have crashed and that you need to restart or whatever.
So really it depends on what your custom exceptions mean. If they just mean "You want to retry this" then that is different from an exception saying "Data integrity has been compromised: 0==1". both of these may be custom so really its for you to decide where to handle things.
Yes, you can call a static exception handler inside a catch block and it will likely be threadsafe as long as you don't reference any static variables.
You should look at Microsoft's Enterprise Library. It has nearly this same design but uses exception policies defined in the web.config to control how the exception is bubbled, wrapped or discarded. Couple that with the Application Logging block and you have a complete solution.
In itself there aren't any technical problems having a static method to handle exceptions / rethrow exceptions, however from a best practices point of view having a single method that magically "handles" exceptions strikes me as a potential code smell. Exceptions are by their very name exceptional, each individual case requires thought to go into it to make sure that you are doing the correct thing and so I find it unlikely that your HandleException method will always be doing something sensible.
As an extreme example I know of one such application where pretty much every single method was wrapped in a try-catch block with a call to an static exception handler method which threw a generic MyApplicationException type. This is an extremely bad idea:
It clutters the code
It makes it harder to make sense of stack traces
It makes it very difficult for callers to catch and handle specific exceptions types
It makes throwing an exception an even bigger performance penalty than before
My favourite was a method which wasn't implemented which looked a bit like this:
void SomeException()
{
try
{
throw new NotImplementedException();
}
catch(Exception ex)
{
throw ExceptionHandler.HandleException(...);
}
}
The worst bit of this of course that it is completely mindless. As I said before exceptions are exceptional - each try ... catch block requires careful thought and consideration to be put into how it should behave, the use of a generic HandleException method is an immediate warning flag that this probably isn't the case.
Rethrowing exceptions
Generally speaking you should only rethrow an exception in two cases:
When you want to add contextual information to an exception (such as the name of the current file being processed)
When you had to catch an exception in order to handle some specific case, e.g. handling an "out of disk space" error
catch (IOException ex)
{
long win32ErrorCode = Marshal.GetHRForException(ex) & 0xFFFF;
if (win32ErrorCode == ERROR_HANDLE_DISK_FULL || win32ErrorCode == ERROR_DISK_FULL)
{
// Specific "out of disk space" error handling code
}
else
{
throw;
}
}
"Bubbling" (i.e. catching and rethrowing an exception without doing anything with it) is completely unneccessary - this is what exceptions are already designed to do all by themselves!
Handling exceptions
Other people have said "exceptions should be handled where it makes sense" and I have even given this advice myself, but in hindsight I don't think thats particularly useful advice! :)
What people generally mean by that is that you should handle exceptions for specific reasons, and that you should choose where in your application to handle that exception depending on that reason.
For example if you want to display an error message to inform the user that they don't have permission to modify a file if you get an access denied error then you may have a specific try-catch block in your UI code that does this:
catch (IOException ex)
{
long win32ErrorCode = Marshal.GetHRForException(ex) & 0xFFFF;
if (win32ErrorCode == ERROR_ACCESS_DENIED)
{
// Display "access denied error"
}
else
{
throw;
}
}
Note that this is very specific to this one case that we wish to handle - it catches only the specific exception type were are interested in and performs additional checks to filter down to the specific case we are interested in.
Alternatively if you want to log unhandled errors or gracefully display error messages to the user instead of an IIS 505 error screen then the place to do this is either in Global.asax or through a custom error page - ASP.Net Custom Error Pages
My point is that when handling exceptions we are are thinking carefully about what it is we want to achieve in terms of application functionality (e.g. retry logic, error messages, logging etc...) and implementing our exception handling logic to specifically address those requirements in the most targeted way possible - there is no magic exception handing framework and there is no boilerplate code.
Avoid exceptions entirely whenever possible!
I usually find that the best strategy is simply to avoid exceptions entirely whever possible! For example if your page parses user enter numbers and you want to display validation messages when they enter stupid values then validate your input up-front instead of catching exceptions:
Bad:
void DoSomething()
{
int age = int.Parse(ageTextBox.Text);
if (age < 0)
{
throw new ArgumentOutOfRangeException("age must be positive");
}
if (age >= 1000)
{
throw new ArgumentOutOfRangeException("age must be less than 1000");
}
}
void Button_Click(object sender, EventArgs e)
{
try
{
DoSomething();
}
catch (Exception ex)
{
DisplayError(ex.Message);
}
}
Good:
void Button_Click(object sender, EventArgs e)
{
int age;
if (!int.TryParse(ageTextBox.Text, out age))
{
DisplayError("Invalid age entered");
}
if (age < 0)
{
DisplayError("age must be positive");
}
if (age >= 1000)
{
DisplayError("age must be less than 1000");
}
DoSomething();
}
Users enter invalid data all of the time - handling this is really application logic and shouldn't fall into the real of exception handling - its certainly not an event that I would call "exceptional".
Of course this isn't always possible, however I find that using this strategy simplifies the code and makes it easier to follow application logic.
First of all we need to consider Exception types, In any business exception can be either BusinessException or Technical/SystemException.
In BusinessException we can send custom exceptions with error
details.
In Technical/System Exception we should not handle it, but let it
popup to UI layer.UI Can decide what error should be displayed in
case of exceptions.
In your approaches, if you handle exception or throw the custom
exception the call trace is lost.
As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
What are some of the most common mistakes you've seen made when handling exceptions?
It seems like exception handling can be one of the hardest things to learn how to do "right" in .Net. Especially considering the currently #1 ranked answer to Common programming mistakes for .NET developers to avoid? is related to exception handling.
Hopefully by listing some of the most common mistakes we can all learn to handle exceptions better.
What are some of the most common mistakes you've seen made when handling exceptions?
I can think of lots.
First read my article on categorization of exceptions into vexing, boneheaded, fatal and exogenous:
http://ericlippert.com/2008/09/10/vexing-exceptions/
Some common errors:
Failure to handle exogenous exceptions.
Failure to handle vexing exceptions.
Construction of methods that throw vexing exceptions.
Handling exceptions that you actually cannot handle, like fatal exceptions.
Handling exceptions that hide bugs in your code; don't handle a boneheaded exception, fix the bug so that it isn't thrown in the first place
Security error: failure to the unsafe mode
try
{
result = CheckPassword();
if (result == BadPassword) throw BadPasswordException();
}
catch(BadPasswordException ex) { ReportError(ex); return; }
catch(Exception ex) { LogException(ex); }
AccessUserData();
See what happened? We failed to the unsafe mode. If CheckPassword threw NetworkDriverIsAllMessedUpException then we caught it, logged it, and accessed the user's data regardless of whether the password was correct. Fail to the safe mode; when you get any exception, assume the worst.
Security error: production of exceptions which leak sensitive information, directly or indirectly.
This isn't exactly about handling exceptions in your code, it's about producing exceptions which are handled by hostile code.
Funny story. Before .NET 1.0 shipped to customers we found a bug where it was possible to call a method that threw the exception "the assembly which called this method does not have permission to determine the name of file C:\foo.txt". Great. Thanks for letting me know. What is stopping said assembly from catching the exception and interrogating its message to get the file name? Nothing. We fixed that before we shipped.
That's a direct problem. An indirect problem would be a problem I implemented in LoadPicture, in VBScript. It gave a different error message depending upon whether the incorrect argument is a directory, a file that isn't a picture, or a file that doesn't exist. Which means you could use it as a very slow disk browser! By trying a whole bunch of different things you could gradually build up a picture of what files and directories were on someone's hard disk. Exceptions should be designed so that if they are handled by untrustworthy code, that code learns none of the user's private information from whatever they did to cause the exception. (LoadPicture now gives much less helpful error messages.)
Security and resource management error: Handlers which do not clean up resources are resource leaks waiting to happen. Resource leaks can be used as denial-of-service attacks by hostile partial trust code which deliberately creates exceptions-producing situations.
Robustness error: Handlers must assume that program state is messed up unless handling a specific exogenous exception. This is particularly true of finally blocks. When you're handling an unexpected exception, it is entirely possible and even likely that something is deeply messed up in your program. You have no idea if any of your subsystems are working, and if they are, whether calling them will make the situation better or worse. Concentrate on logging the error and saving user data if possible and shut down as cleanly as you can. Assume that nothing works right.
Security error: temporary global state mutations that have security impacts need to be undone before any code that might be hostile can run. Hostile code can run before finally blocks run! See my article on this for details:
http://blogs.msdn.com/ericlippert/archive/2004/09/01/224064.aspx
Re-throwing exceptions like this:
try
{
// some code here
}
catch(Exception ex)
{
// logging, etc
throw ex;
}
This kills the stack trace, making is far less usable. The correct way to rethrow would be like this:
try
{
// some code here
}
catch(Exception ex)
{
// logging, etc
throw;
}
Catching all exceptions when in many cases you should attempt to catch specific exceptions:
try {
// Do something.
} catch (Exception exc) {
// Do something.
}
Rather than:
try {
// Do something.
} catch (IOException exc) {
// Do something.
}
Exceptions should be ordered from most specific to least.
Rethrowing an exception with a meaningless message.
try
{
...
}
catch (Exception ex)
{
throw new Exception("An error ocurred when saving database changes").
}
You won't believe how often I see code like this running in production.
Nobody is talking about seeing empty catch blocks like these....
try{
//do something
}
catch(SQLException sqex){
// do nothing
}
Also never use Exception handling for creating alternate method flows...
try{
//do something
}catch(SQLException sqex){
//do something else
}
Not using using on IDisposable objects:
File myFile = File.Open("some file");
callSomeMethodWhichThrowsException(myFile);
myFile.Close();
myFile does not get closed until myFile's finalizer is called (which may be never) because an exception was thrown before myFile.Close() was called.
The proper way to do this is
using(File myFile = File.Open("some file"))
{
callSomeMethodWhichThrowsException(myFile);
}
This gets translated by the compiler into something like:
File myFile = File.Open("some file");
try
{
callSomeMethodWhichThrowsException(myFile);
}
finally
{
if(myFile != null)
myFile.Dispose(); //Dispose() calls Close()
}
So the file gets closed even in the face of exceptions.
Forget to set the inner exception when rethrowing a catched exception
try
{
...
}
catch (IOException ioException)
{
throw new AppSpecificException("It was not possible to save exportation file.")
// instead of
throw new AppSpecificException("It was not possible to save exportation file.", ioException);
}
When I posted this answer, I forget to mention that we should always consider when to include inner exception or not due to security reasons. As Eric Lippert pointed out on another answer for this topic, some exceptions can provide sensitive information about the implementation details of the server. Thus, if the caller who will be handling the exception is not trusted, it is not a good idea to include the inner exception information.
Empty catch:
//What's the point?
catch()
{}
Rethrowing:
//Exceptions are for *adding* detail up the stack
catch (Exception ex)
{throw ex;}
Assuming an exception that covers many scenarios was something specific. A real life scenario was a web app where the exception handling always assumed all errors were session time outs and logged and reported all errors as session time outs.
Another example:
try
{
Insert(data);
}
catch (SqlException e)
{
//oh this is a duplicate row, lets change to update
Update(data);
}
To log Exception.Message instead of Exception.ToString()
Many times, I see code logging only the exception message while it should log the return of ToString method. ToString provides much more information about the exception than the Message. It includes information like inner exception and stack trace besides the message.
Trying to catch OutOfMemoryException or StackOverflowException - those lead to a shutdown of the runtime, hence to way to catch them from within the same Process (or even from the CLR as a whole?)
OutOfMemoryException: The exception that is thrown when there is not enough memory to continue the execution of a program.
"Starting with the .NET Framework version 2.0, a StackOverflowException object cannot be caught by a try-catch block and the corresponding process is terminated by default. Consequently, users are advised to write their code to detect and prevent a stack overflow."
Failing to catch possible exceptions inside a catch handler. This can cause the wrong exception to be propagated upwards.
For example:
try
{
DoImportantWork();
}
catch
{
Cleanup();
throw;
}
What happens if Cleanup() throws an exception? You don't want to see an Exception pointing to the Cleanup() method in this catch handler. You want the original error. You could try to log the cleanup error, but even your logging code needs exception handling to avoid throwing exceptions from it.
try
{
DoImportantWork();
}
catch
{
try
{
Cleanup();
}
catch
{
// We did our best to clean up, and even that failed.
// If you try to log this error, the logging may throw yet another Exception.
}
throw;
}
Wrong
try
{
// Do something stupid
}
catch
{
// ignore the resulting error because I'm lazy, and later spend
// a week trying to figure out why my app is crashing all over
// the place.
}
Better
try
{
/// do something silly.
}
catch (InvalidOperationException ex)
{
/// respond, or log it.
}
catch (Exception e)
{
/// log it.
}
Using exceptions for normal flow control. Exceptions should exceptional. If it's a good / expected operation, use return values, etc.
I want to catch all exceptions raised (handled or unhandled) to log them. for unhandled i use ThreadExceptionEventHandler and UnhandledExceptionEventHandler but i want to catch and exceptions that are in try catch block with or without (Exception e). It's possible to inherit the exceptions class to create a general event?
Starting from Windows XP you can get notified about every raised exception, even before it's known to be handled or not.
This is available via so-called "vectored" exception handling, which is actually a little addition to the standard structured exception handling.
Call AddVectoredExceptionHandler to add your own handler. You'll get called right after the exception is raised, either by explicit throw/__CxxThrowException/RaiseException or implicitly by the processor (access violation or etc.)
You can log the exception in your handler (produce stack dump for instance), and return EXCEPTION_CONTINUE_SEARCH.
Inheriting from Exception to provide your own Exception class would work fine for exceptions you generate in your code, and you could use the inner exception constructor to carry built in exceptions up the chain.
If you were goig to try that, you'd need to replace all of your exception handling code, and probably add a chunk more as well. I don't think it'd be substantially better than Peter McG's approach, but it might allow you different options when preserving & examining the original exceptions and re-throwing, for example keeping a record of whether it has already been logged lower down the chain.
Just to be explicit, it is possible to use:
catch (Exception e)
{
log(e);
throw;
}
which will rethrow the original exception.
Sounds like you've got the Unhandled Exceptions as covered as possible, for handled exceptions can't you just eventually...
catch (Exception e) {}
and call the same logging function with the instance.
If not and you really must have some instances where you have a catch but without catching an instance you can use...
catch { throw; }
to re-throw the exception to be eventually caught and logged as an un-handled exception.
C++ allows for catch(...) which catches all exceptions but doesn't really allow to analyze them in depth. (see using catch(...) (ellipsis) for post-mortem analysis )
I'm not sure if it will work in C# though.
No, thats not possible.
The only way this would be possible is using the debugging APIs (the managed version is named mdbg)
There's no way to catch an already caught exception except, may be, working with AddVectoredExceptionHandler.
Having said that, you can use a catch-and-rethrow approach:
catch(Exception e) {
Logger.Log(e);
throw;
}
or
catch(Exception e) {
bool rethrow = LoggerStrategy.Log(e);
if(rethrow) { throw; }
}
Better still, use the Logging Application Block.
I read a lot about how bad catching base Exceptions is and I have to confess that I did it also:
try{
...
}
catch (Exception exception){
MessageBox.Show(exception.Message, "Error!");
MyLogger.Log(exception.Message);
}
Now I would like to do it right and have some questions about it:
Which exceptions should I catch (for example FileNotExists for file manipulation, but what for TableAdapter or ReportClass (CrystalReports))
Where can I see a list of exceptions, that an objects can throw (for example TableAdapter)
Where in Windows Forms Application can I set a static method, which will log any exception to a file for example
Any other suggestions?
Catch whichever exceptions you can reasonably handle. For example, if you're trying to open a file for writing, you should expect that maybe the file is marked read-only, so that would throw an exception. But in the same situation you wouldn't try to catch a null argument exception, because that would be due to programmer error.
They should be found in the function reference in MSDN (you'll have to look it up on each one). For user-defined functions, you'll have to go digging, unless there is additional documentation or summary commentary.
3, 4. Consider using a logging library for .NET
I have one thing to add. If you just want to log an exception without affecting program flow you can always do this:
try
{
...
}
catch (Exception exception)
{
MyLogger.Log(exception.Message);
throw;
}
That's up to you to decide which exceptions your application logic can reasonably expect to recover from.
Exceptions are thrown by method invocations, not objects. In Visual Studio, Intellisense explanations will tell you which exceptions are thrown by an object (provided that the XML documentation describes which exceptions a method throws.
Rather than use a static method, respond to the Application.ThreadException event. The link provided has examples.
MSDN
You can set an event for unhandled exceptions in application events file
(got a VB sample here but i hope you get the point)
Private Sub MyApplication_UnhandledException(ByVal sender As Object, ByVal e As Microsoft.VisualBasic.ApplicationServices.UnhandledExceptionEventArgs) Handles Me.UnhandledException
End Sub
You can find the application events in the options of you project.
You should only catch exceptions you can do something about, really.
That's the rule of thumb. I typically have a try/catch around my Program.Main just in case an exception bubbles right to the top and needs logging. You can also handle the CurrentDomain_UnhandledException event, in case exceptions are thrown in other threads than the UI thread (assuming you are multithreading).
In response to "4. Any other suggestions?":
In your example code, a message box is displayed before logging the exception. I would recommend logging the exception before displaying the message, just in case the user sees the error message, panics, and goes on vacation without clicking "OK". It's a minor thing, but message boxes block the program indefinitely and should be used with discretion!
Edit: I have looked at the answers code: NONE of them do what I want (I've checked). It would seem that there is no way to do what I want in native c#. I guess that's not a disaster just a shame given that .NET does support it (see accepted answer).
Thanks all.
I have c# code (part of a test framework that will never be run except under a debugger) like this who's point it to avoid actually catching the exception as that makes debugging the code in the unwound part of the stack a royal pain.
Bool bad = true;
try
{
MightThrow();
bad = false;
}
finally
{
if(bad) DoSomeLoggingOnFailure();
//// Does not catch!!!!
//// exception continues to unwind stack.
//// Note that re throwing the exception is NOT
//// the same as not catching it in the first place
}
is their a better way to do this?
A solution would have to behave exactly like that under the debugger with regards to un-caught exceptions. It would have to result in the only one first chance exception and the debugger breaking at the point that the exception was originally thrown, not in a catch block.
Specifically I need the debugger on un-caught exceptions to stop a in side MightThrow.
The following doesn't work because it fails to have the debugger break in the correct place
try { ... } catch { throw; }
And this doesn't work because it loses stack info (and also breaks in the wrong place).
try { ... } catch(Exception e) { throw e; }
I known that in D I could use a scope(failure) block
So, in .NET what you're asking for is theoretically possible, but it's not going to be easy.
CIL actually defines five types of exception handling block! The try, catch and finally ones you're used to in C#, and two others:
filter - similar to a catch block but can run arbitrary code to determine whether it wants to handle the error, rather than just matching on type. This block has access to the exception object, and has the same effect on the exception stack trace as a catch block.
fault - similar to a finally block, however it is only run when an exception occurs. This block does not have access to the exception object, and has no effect on the exception stack trace (just like a finally block).
filter is available in some .NET languages (e.g. VB.NET, C++/CLI) but is not available in C#, unfortunately. However I don't know of any language, other than CIL, that allows the fault block to be expressed.
Because it can be done in IL means not all is lost, though. In theory you could use Reflection.Emit to dynamically emit a function that has a fault block and then pass the code you want to run in as lambda expressions (i.e. one for the try part, one for the fault part, and so on), however (a) this isn't easy, and (b) I'm unconvinced that this will actually give you a more useful stack trace than you're currently getting.
Sorry the answer isn't a "here's how to do it" type thing, but at least now you know! What you're doing now is probably the best approach IMHO.
Note to those saying that the approach used in the question is 'bad practice', it really isn't. When you implement a catch block you're saying "I need to do something with the exception object when an exception occurs" and when you implement a finally you're saying "I don't need the exception object, but I need to do something before the end of the function".
If what you're actually trying to say is "I don't need the exception object, but I need to do something when an exception occurs" then you're half way between the two, i.e. you want a fault block. As this isn't available in C#, you don't have an ideal option, so you may as well choose the option that is less likely to cause bugs by forgetting to re-throw, and which doesn't corrupt the stack trace.
How about this:
try
{
MightThrow();
}
catch
{
DoSomethingOnFailure();
throw; // added based on new information in the original question
}
Really, that's all you did. Finally is for things that must run regardless of whether an exception occurred.
[Edit: Clarification]
Based on the comments you've been mentioning, you want the exception to continue being thrown without modifying its original stack trace. In that case, you want to use the unadorned throw that I've added. This will allow the exception to continue up the stack and still allow you to handle part of the exception. Typical cases might be to close network connections or files.
[Second edit: Regarding your clarification]
Specifically I need the debugger on
un-caught exceptions to stop at the
original point of the throw (in
MightThrow) not in the catch block.
I would argue against ever breaking a best-practice (and yes, this is a best-practice for partially handling exceptions) to add some minor value to your debugging. You can easily inspect the exception to determine the location of the exception throw.
[Final edit: You have your answer]
kronoz has thoughtfully provided you with the answer you sought. Don't break best practices -- use Visual Studio properly! You can set Visual Studio to break exactly when an exception is thrown. Here's official info on the subject.
I was actually unaware of the feature, so go give him the accepted answer. But please, don't go trying to handle exceptions in some funky way just to give yourself a hand debugging. All you do is open yourself up to more bugs.
If you're interested in the debugger simply stopping precisely where the exception occurred then have you considered first-chance exceptions?
If you open Tools|Exceptions then tick the Common Language Runtime Exceptions box, the debugger will stop at the point of exception regardless of any try/catch/finally blocks.
Update: You can specify the precise exception you wish to catch by expanding the [+] tree in the Exceptions dialog. Though of course it will fire every time any exception of the specified type[s] occur[s], you can switch it on and off at will even in the middle of a debugging session, so with judicious use of breakpoints you can get it to do your bidding. I used it successfully to get around the 'target of an invocation has thrown an exception' ball ache originating from using reflection to instantiate objects. Very useful tool in such circumstances. Also note the locals and stack trace should be firmly available as far as I recall (just did a quick test and they are available), so no problems there.
Of course if you want to log things then that is outside the scope of an IDE debugger; and in which case first-chance exceptions won't help you!
Give it a go at least; I found them very useful and they might be more appropriate for your issue than you think.
What's wrong with:
try
{
MightThrow();
}
catch
{
DoSomthingOnFailure();
throw;
}
For code that should only run on exceptions, use the catch block:
try
{
MightThrow();
}
catch (Exception ex)
{
// this runs only when there was an exception
DoSomthingOnFailure();
// pass exception on to caller
throw;
}
finally
{
// this runs everytime
Cleanup();
}
This is what you want. It will only call this method when an error occurs, and the "throw" statement will re-throw the exception with the callstack intact.
try
{
MightThrow();
}
catch
{
DoSomthingOnFailure();
throw;
}
A "finally" block that runs only on failure is called "catch" (with no parameters). :-)
Now, there is a small caveat. If you want to have a specialised "catch" case for a particular exception type and have a generic "catch" that works for all exceptions, you'll have to do a bit of a custom logic.
Thus, I would do something like:
try
{
MightThrow();
}
catch(MyException ex)
{
// Runs on MyException
MySpecificFailureHandler()
// Since we have handled the exception and can't execute the generic
// "catch" block below, we need to explicitly run the generic failure handler
MyGenericFailureHandler()
}
catch
{
// Runs on any exception hot handled specifically before
MyGenericFailureHandler()
// If you want to mimic "finally" behavior and propagate the exception
// up the call stack
throw;
}
finally
{
// Runs on any failure or success
MyGenericCleanupHandler();
}
Every example so far is losing the original StackTrace according to my tests. Here's a solution that should work for you.
private static void PreserveStackTrace(Exception exception)
{
MethodInfo preserveStackTrace = typeof(Exception).GetMethod("InternalPreserveStackTrace",
BindingFlags.Instance | BindingFlags.NonPublic);
preserveStackTrace.Invoke(exception, null);
}
try
{
MightThrow();
}
catch (Exception ex)
{
DoSomethingOnFailure();
PreserveStackTrace(ex);
throw;
}
How about only catching an exception that "MightThrow" does not throw?
Bool bad = true;
try
{
MightThrow();
bad = false;
}
catch (SomePrivateMadeUpException foo)
{
//empty
}
finally
{
if(bad) DoSomeLoggingOnFailure();
}
Let me recap your requirements the way I understand them:
You want some code that is run only when an exception is generated, in order to do some logging.
You want to run your test framework under debugger and break at the point at which the exception is thrown.
To meet your first requirement, you should write the code the way everybody suggested - using parameterless catch and throw.
To meet your second requirement while using the parameterless catch, you could configure your debugger to break when an exception is throw, not only when there's an unhandled exception. I suspect you know how to do it, but I'll put it here for answer completeness: in VS you can do that in Debug -> Exception -> Common Language Runtime Exceptions -> check the Thrown checkbox.
If you know that your app throws a lot of handled exceptions, that might not be an option for you. At that point, your only choice left to meet your first requirement is to either write the code to use finally for exception logging purposes or look into the direct IL emitting route as Greg Beech suggests.
However, whether the finally code is being executed depends on the debugger you are using. In particular, VS will break on an unhadled exception before the finally is executed and will not let you continue. Thus, unless you detach from the process at that point, your logging code will never be executed. In other words, the second requirement will interfere with meeting the first requirement.
You could encapsulate your logic in a custom class, something like:
public class Executor
{
private readonly Action mainActionDelegate;
private readonly Action onFaultDelegate;
public Executor(Action mainAction, Action onFault)
{
mainActionDelegate = mainAction;
onFaultDelegate = onFault;
}
public void Run()
{
bool bad = true;
try
{
mainActionDelegate();
bad = false;
}
finally
{
if(bad)
{
onFaultDelegate();
}
}
}
}
And use it as:
new Executor(MightThrow, DoSomeLoggingOnFailure).Run();
Hope this helps.
Isn't this the same as:
try
{
MightThrow();
}
catch (Exception e)
{
DoSomethingOnFailure();
throw e;
}
?
You could write, or have someone write for you, a small assembly in VB.net which implements a TryFaultCatchFinally(of T) method that accepts four delegates:
TryMethod -- An Action(of T) to perform the "Try" block.
FaultMethod -- A Predicate(Of T, Exception) which, if an exception occurs, will be called before any "finally" blocks run; if it returns true the Catch block will run--otherwise it won't.
CatchMethod -- An Action(Of T, Exception) to be performed if an exception had occurred and FaultMethod returned true; happens after "finally" blocks run.
FinallyMethod -- An Action(OF T, Exception, Boolean) to be performed as a "Finally" block. The passed-in exception will be null if TryMethod ran to completion, or will hold the exception that caused it to exit. The Boolean will be true if the exception was caught, or false otherwise.
Note that when the FaultMethod is executed, one may be able to examine the state of objects that caused the exception, before such state is destroyed by Finally blocks. One must use some care when doing this (any locks that were held when the exception was thrown will continue to be held) but the ability may still sometimes be handy, especially when debugging.
I'd suggest the routine look something like:
Shared Sub TryFaultCatchFinally(Of T)(ByVal TryProc As Action(Of T), _
ByVal FaultProc As Func(Of T, Exception, Boolean), _
ByVal CatchProc As Action(Of T, Exception), _
ByVal FinallyProc As Action(Of T, Exception, Boolean), _
ByVal Value As T)
Dim theException As Exception = Nothing
Dim exceptionCaught As Boolean = False
Try
TryProc(Value)
theException = Nothing
exceptionCaught = False
Catch Ex As Exception When CopyExceptionAndReturnFalse(Ex, theException) OrElse FaultProc(Value, Ex)
exceptionCaught = True
CatchProc(Value, Ex)
Finally
FinallyProc(Value, theException, exceptionCaught)
End Try
End Sub
No, I think this is a common idiom the way you have it.
EDIT
To be clear, the "catch" then "rethrow" strategies offer the same run-time semantics, however they change the experience when the VS debugger is attached. Tooling and maintenance is important; debugging often requires you to 'catch all first-chance exceptions' and if you end up with lots of 'spurious' first-chance exceptions due to catch-then-rethrow in your code, it really hurts the ability to debug the code. This idiom is about interacting well with the tooling, as well as clearly expressing the intent (you don't want to 'catch', decide can't handle, and rethrow, instead you just want to log that an exception did happen but let it pass on by).
Have you considered using the DebuggerStepThrough attribute?
http://msdn.microsoft.com/en-us/library/system.diagnostics.debuggerstepthroughattribute.aspx
[DebuggerStepThrough]
internal void MyHelper(Action someCallback)
{
try
{
someCallback();
}
catch(Exception ex)
{
// Debugger will not break here
// because of the DebuggerStepThrough attribute
DoSomething(ex);
throw;
}
}
With exception filters added in C# 6, one option is to make use of a false returning exception filter, like so:
void PerformMightThrowWithExceptionLogging()
{
try
{
MightThrow();
}
catch (Exception e) when (Log(e))
{
// Cannot enter here, since Log returns false.
}
}
bool Log(Exception e)
{
DoSomeLoggingOnFailure(e);
// Return false so the exception filter is not matched, and therefore the stack is kept.
// This means the debugger breaks where the exception actually happened, etc.
return false;
}
See https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/try-catch for more details on exception filters.
try
{
MightThrow();
}
catch
{
DoSomethingOnFailure();
}