Related
So I have been doing some research into how I should be doing try-catch-finally blocks and there is some conflicting information in every post I read. Can someone clarify?
One common idea is to not catch exceptions that you do not know what to do with at that point in the code. The exception will bubble up until it presumably gets to a global exception handler if nothing else catches it. So at that point you display a message to the user that an unknown type of exception occurred, log it, etc.
Now after reading it sounds like this is the only exception handler that you will need? You should not be using it for flow control, so you should be checking if something is returned as null or is invalid causing the exception and correcting it in code. ie. testing for null and doing something about it before it can cause the exception.
But then there are other things such as running out of memory that you would not be able to test for, it would just occur during an operation and the exception would be thrown. But I would not be able to do anything about this either so this would be bubbled up to the global handler.
I think there are some that I am missing, like when dealing with files there can be some thrown from the external code. File not found exception seems like one that may come up often, so I would catch it and in the finally block gracefully close down anything I opened related to other code/processing and then notify the user and log it right there?
The only reason why you would want to catch an exception is for the finally part of the block to make sure that whatever you started before the exception is closed/finalized in a known state? But even then you would want to throw this exception after performing these tasks so the user is notified by the global exception handler, there is no point duplicating this code at this point?
So other than a global exception handler you would have try-catch-finally blocks for these scenarios.
So assuming that I am missing something here, there may be the possibility that you want to try and catch a specific type of exception and then do something with it. I cannot think of anything that you would want to do in the catch block though since the global one would log/notify the user and if you have an exception that usually means that there is no deal for the code to continue on.
Is there any easy way to know which exceptions will be thrown from which modules? I think the only way I have read is to read the MSDN or component suppliers documentation, other than that there is no way to know what exception you would be trying to catch if you were looking for a specific one (not sure why you would)
This question came up since in my application I had a section of code in a try-catch block, and it ended up that when an exception occurred it was either because an object was null, or a string was invalid. Once I wrote code to handle those scenarios the try-catch block is no longer needed, if an exception is encountered now there is nothing the code can do to recover so it should be logged and let the user know so it can be fixed.
But this goes against what I have been reading and what has been preached to me, bad code is code with no try-catch blocks. So how does this all tie together and what piece am I missing here?
The first part of your question is all correct: you should only catch exceptions that you know how to handle. Otherwise, just let them bubble up until they reach code that can handle them.
(Note that "handle" doesn't mean "log" or "display an error". It means to correct the problem that caused the exception, or work around it in some way.)
If they never encounter code that can handle them, or if they are unhandlable exceptions (like OutOfMemory), then they will eventually reach the global unhandled exception handler. This is where you will log the exception (if appropriate), display a generic error to the user (if appropriate), and more often than not, terminate the application. You cannot simply continue as if nothing happened—the exception indicates that the application is in an unexpected state. If you try and continue, you're just going to crash, or worse.
I think there are some that I am missing, like when dealing with files there can be some thrown from the external code. File not found exception seems like one that may come up often, so I would catch it and in the finally block gracefully close down anything I opened related to other code/processing and then notify the user and log it right there?
FileNotFound is a good example of an exception that you will want to handle locally. In the same method (or perhaps one level up, in your UI code) that attempts to load the file, you'll have a catch block for FileNotFound exceptions. If appropriate, display a friendly error message to the user and ask them to choose another file. If it's internal code, give up and try something else. Whatever you need to do. There are few good reasons for FileNotFound to bubble up outside of your code.
This is sort of like using exceptions for flow control, but unavoidable. There is no way to avoid using exceptions (or error codes) for I/O, so you just need to handle the failure case. You could try and verify that the file exists first, before trying to open it, but that would not solve the race issue wherein the file gets deleted or becomes otherwise inaccessible between the time your verification code runs and when you actually try and open it. So now all you've done is duplicated your error-handling code in two places, which serves little purpose.
You have to handle exceptions like FileNotFound locally. The further away from the code that throws, the less likely you can do anything reasonable about it.
Another good example of this, aside from I/O-related exceptions, is a NotSupportedException. For example, if you try to call a method that isn't supported, you might get this exception. You will likely want to handle it and have code in the catch block that falls back to a safe alternative.
The only reason why you would want to catch an exception is for the finally part of the block to make sure that whatever you started before the exception is closed/finalized in a known state? But even then you would want to throw this exception after performing these tasks so the user is notified by the global exception handler, there is no point duplicating this code at this point?
This does not require catching the exception. You can have a try block with only a finally block. A catch block is not required. In fact, this is precisely what using statement implements. If you have state that needs to be cleaned up in the event of an exception being thrown, you should implement the IDisposable pattern and wrap usage of that object in a using block.
Is there any easy way to know which exceptions will be thrown from which modules? I think the only way I have read is to read the MSDN or component suppliers documentation, other than that there is no way to know what exception you would be trying to catch if you were looking for a specific one (not sure why you would)
Precisely. This is not really a problem, though, since you are only catching the exceptions that you can do something about. If you don't know that a module can throw a particular exception, you obviously can't have written code that can handle that exception.
The documentation will tell you all of the important exceptions that you might need to handle, like FileNotFound, SecurityException, or what have you.
This question came up since in my application I had a section of code in a try-catch block, and it ended up that when an exception occurred it was either because an object was null, or a string was invalid. Once I wrote code to handle those scenarios the try-catch block is no longer needed, if an exception is encountered now there is nothing the code can do to recover so it should be logged and let the user know so it can be fixed.
Avoiding exceptions in the first place is always the best option. For example, if you can design your application so that a null object or invalid string is impossible, great. That is what we call robust code. In that case, you don't need to catch these exceptions because there's no way that you can handle it. You thought you already handled the problem, so if an exception is getting thrown anyway, it is a sign of a bug. Don't gloss over it with a catch block.
But sometimes, catch blocks are still necessary, and you write code inside of the catch block to handle the problem. In that case, there's probably no reason to re-throw the exception or log it, so you don't have any code duplication.
But this goes against what I have been reading and what has been preached to me, bad code is code with no try-catch blocks. So how does this all tie together and what piece am I missing here?
Completely wrong. I don't know where you've been reading that, but it is nonsense. Exceptions are exceptional conditions. If your code has catch blocks strewn all over it, that is a sign that you are doing it wrong. Either you're using exceptions for flow control, you're swallowing exceptions in a misguided attempt to "improve reliability", or you don't know about the global unhandled exception handler.
Doesn't sound like you're missing anything to me.
The only thing I feel compelled to mention that doesn't fit strictly into any of your questions is that sometimes you might want to catch an exception and rethrow it as a different exception. The most common situation where you would do this is if you were designing a library of re-usable code. Inside of the library, you might catch internal exceptions and, if you cannot handle them, rethrow them as general exceptions. The whole point of a library is encapsulation, so you shouldn't let exceptions bubble up that the caller cannot possibly do anything about.
There is no true guide for exceptions management (raising and handling). Every app has to decide what level of flow control should be used and how exception has to be raised/handled.
General rules are:
exceptions are raised in exceptional situations
handle exception you can handle and do meaningful things for your app so
exception raising can be used in flow control, actually it's the only way you can reliably handle flow control when you are dealing with devices, so hardware interrupts. (printers, bill validators, file transfer...)
The rest is up to you. The meaning of exception management is made by you.
Imagine you need to download some files from an FTP server, one you don't control. Of course you can't trust other people so you need to prepare for temporary outages and such. So you wrap your downloading code in a try-catch-block and look for WebException if you catch one you might check for FtpStatusCode.ActionNotTakenFileUnavailableOrBusy if that was the error you simply retry. Similarly if you call a web service a 404 might be trouble, but a 429 means that you wait a little and retry, because you had been rate-limited.
Usually you can know which exceptions can be thrown by experience or documentation but C# lacks checked exceptions. Things like NullPointerException or ArgumentNullException can be properly handled with guards in your code. But other things, like errors external dependencies can sometimes be caught and handled by you without crashing the application.
Possibly an obvious question to some but couldn't find a duplicate.
I'm packaging the final version of a Windows Forms solution I've been working on and am getting it ready for online distribution. What are the best practices when doing so? We've already had some trouble with packaging the installation file and have run into hurdles to test the program on different PCs, both 32 and 64-bit included.
More specifically, should "throw;" commands be commented out or left in the final release? Would this expose any of the inner workings of the solution itself?
Released application should not crash when exception occurs. You will want to inform the user, something went wrong and log your exception, but you do not want to crash! Informing user should be done in a friendly manner and not just by putting exception.ToString() into the message box.
It is a good practice to add Application.ThreadException or AppDomain.CurrentDomain.UnhandledException handlers to handle all exceptions in your Application. How exactly to do that, is answered in the following thread: Catch Application Exceptions in a Windows Forms Application
However, make sure that your application survives in a usable state, i.e. handle exceptions in a proper way for your application.
I usually add a preprocessor directive for handling exceptions on the application level, since I want them to trow while debugging. For example:
#if !DEBUG
Application.ThreadException += new ThreadExceptionEventHandler(MyHandler);
#endif
It should also be mentioned, that if you have code pieces where you anticipate that Exception might occur, such as network communication error, you should handle those pieces explicitly. What I am saying is, we should not completely forget about exception handling, just because we configured an unhandled exception handler on the application level.
Keep all of your exception handling intact.
Add an event to the starting form in the application, attaching to the Application.UnhandledException event. This will fire if an exception propogates up the stack.
This is the point to inform the user that the application has crashed. Log the error here and then abort gracefully.
Your point about revealing internals, thats up to you to decide. You can obfuscate the source code if you wish, but if you are releasing in Release build mode, and you are not providing the .PDB, then this is the first step.
Ultimately, the DLL / EXE can be decompiled anyway, so its up to you. Debug mode will reveal a lot more than Release mode, but not much more.
Ideally, you should be catching anything that's thrown higher with throw;. Carefully check your code and try to ensure that thrown exceptions are dealt with appropriately. Unhandled exceptions are logged - you can see this information in the Windows Event Viewer. Depending on what details you put in them, unhandled exceptions could give clues as to the inner workings of your application. However, I would suggest that unhandled exceptions are a poor source of information, and that anyone who wanted to know how your application worked could simply disassemble it, unless you've obfuscated it.
Some exceptions cannot be caught by surrounding code with try/catch blocks, so your application should also implement an unhandled exception handler. This gives you the opportunity to show the user an error message and do something with the exception - log it, send it to support, discard it, etc.
I have a windows service run as a server. However, the server sometime stops immediately by an error which is un-handled. Please help me how to handle global exception. Thanks.
It sounds to me like you're trying to solve the problem the wrong way around...
When your program (or service) crashes because of an unhandled error, the solution is not to figure out where and how to "handle" all unhandled errors so that you can ignore them and continue execution. I've hashed out that view more clearly in this answer, but the short version is that when you encounter an unhandled exception, the correct thing to do is to crash. As quoted in the original answer:
The fact that an unhandled exception occurred means that the server was in an unexpected state. By catching the exception and saying, "Don't worry, it's all good," you end up leaving a corrupted server running.
[ . . . ]
Catching all exceptions and letting the process continue running assumes that a server can recover from an unexpected failure. But this is absurd. You already know that the server is unrecoverably toast: It crashed!
Much better is to let the server crash so that the crash dump can be captured at the point of the failure. Now you have a fighting chance of figuring out what's going on.
So in fact, the real solution involves figuring out the root cause of the unhandled exception and modifying your code to prevent that error from occurring in the first place.
There's no way that we can help you to do that unless you post the exact exception message that you're getting, and preferably a full stack trace. But you definitely want to preserve the debugging information that you're getting, rather than come up with a way to ignore it entirely—that's the only way to actually solve the problem.
If you still insist on ignoring all well-meaning advice to the contrary, you'll find the "stick your head in the sand and ignore it" approach detailed here.
You could try using the AppDomain.CurrentDomain.UnhandledException event, although I'm not sure if it will catch every single unhandled exception.
First, I'm already familiar with the simple exception handling syntax but I'm asking about the best place, the best time and the best way to deal with them.
I'm building an N-Layered application. so I think the DAL will sometime generate some errors to handle .. and I just learned about the SqlException class, what's the deal with that class ? I once saw a code that handles the SqlException then it handles Exception!
After knowing the practice and where I'm going to handle them, I'm planning to create a method to connect to the database and log the errors in a database so I could fix it but still I don't know what information should I collect to allow me identify the whole situation!
I thought exceptions handling was not a big deal. but every now and then I read some strange advices -that I never understood- on the questions comments but no one could answer me since it was some very old questions!
"Don't just explicitly catch
exceptions"
"the code that is used by
higher-layers in your application must
always only throw exceptions and never
worry about how to deal with them."
EDIT
What about Page_Error event and Application_Error .. I saw that they are a good practice for handling errors
Exception handling is a big deal, and it's not simple to design a good strategy for that.
First of all, some general rules:
Exceptions occur when the running code is completely unable to go ahead, so maybe it tried to handle some internal exceptions but ultimately failed. Think about TCP connection: if a damaged packet arrives, it's an exception, but TCP protocol can handle it. If too many are damaged, an I/O or socket exception is thrown
Exceptions can not always be handled. In almost all cases, when you get an exception from underlying layers you are unable to run corrective code. If your application depends on a DB and that is offline, when you get the exception about it you can only display an error message
Exceptions can be unexpected, and can reveal design or implementation flaws. For example, an implementation flaw can be the situation in which you have a redundant DB but when you fail to connect to frist mirror you don't try with the second
For the third point, it's important to log exceptions and periodically analyse logs to find any weird situation. So, let's begin with the concrete answer.
First of all
think about "handling" the exception. When you write every single code line, think about the possible problems that may prevent it from completing, and think about the possible corrective actions. if any are possible. An error message is not a good handling way, it's the latest strategy.
Don't start to write try-catch(Exception), but prefer specific exceptions. If you need to parse strings to numbers etc, then expect FormatException, if you need to cast from Object to your type expect InvalidCastException
When you write lower-level layers
don't hesitate to throw exceptions!! Don't do like many folks do, ie. return null or use (like ANSI C) a boolean return value and reference parameters. Exceptions are there for that. If you can handle an exception (ie. you don't find a local file but you know you have a remote backup, so handle FileNotFoundException by calling the remote mirror, but if you can't still connect then ultimately throw) then do it and try to resume computation, but if you cannot then throw. And don't forget to throw the inner exception, if present, because it is helpful for logging in the highest layer.
Basically, you can still decide to throw an exception on your own even if you don't catch any! And this is highly recommended especially when function parameters are invalid!
Another good option is to still log in the underlying layers. You actually want to log no matter an exception occurs.
When you log
remember to give an adequate severity to the messages. If you find via code that your DB is offline, that's not an unexpected exception. Still log it as an error, but don't worry about code bugs when you investigate the logs. Instead, if you catch an exception that your code is unable to recognize (a NullReferenceException is a classic example) then log with highest severity, ie. fatal, to give it maximum priority!
A good strategy for ASP.NET
can surely be based upon Page.OnError method. If you have a base page class for all of the pages of your site, you should definitely override that method. In that method, you should first log your exception.
You also shouldn't abuse of try-catch(Exception) blocks, because if you don't catch an exception you can't handle with catch, you will have to handle it via OnError.
When you run such a method, don't immediately think about Server.RemoveError(). You can prefer to have a static HTML page for HTTP 500 error (that is triggered when an unhandled exception bubbles to ASP.NET runtime) that displays a courtesy message to the user.
Briefly
Don't hesitate to throw in underlying layers if anything strange occurs
As said by your advice, don't handle exceptions you are unable to handle (if you catch an exception you can't handle, rethrow it)
LOG!!!!!!!!!!!!!!!!!
Don't disclose exception details to final users on a public website, never!! By default, ASP.NET prevents that from occurring, but you could still use OnError to print stack trace
Use OnError, or Application_Error as single central point to handle all unexpected exceptions
Periodically examine logs against error/fatal messages to find issues with your code, then think about maintaining/debugging/fixing it
Take a look at elmah. It's a logger for asp.net. Renders all errors on a nice summary page.
http://code.google.com/p/elmah/
The best way to handle exceptions is in the specific layer they apply to. If it is a constraint volation, for example, 2 users with the same name, you should let that bubble up to the UI and alert the user.
Same goes with any business rule violations. Those should bubble up to the UI so the end user knows what went wrong.
A SQL Connectivity error is best handled in the DAL...etc..
The how/when/where to catch exceptions may depend on what your trying to do exactly, its difficult to give an exact catch all always correct answer.
As to your specific questions,
I just learned about the SqlException
class, what's the deal with that class
? I once saw a code that handles the
SqlException then it handles
Exception!
Its good practice to handle the specific exception you believe may occur, if your not sure what type this exception is you can just 'Exception', if you want something specific to occur on a 'SQLException' and something else to happen with an 'Exception' then there is certainly nothing wrong with writing code that handles both.
"Don't just explicitly catch
exceptions"
I believe this is refering to code like this
try
{
int i = 1/0;
}
catch(Exception e)
{
//do nothing
}
This exception will be caught but you'll never know it happened, hence this is not a good idea, and the person using the code will be scratching their head as to whats going on.
I think what you are asking here is a Error/Exception Handling Strategy for any application.
I think it includes:
Where - All places where you think an exception can occur or which need more monitoring like DB calls, External Service Calls, Use of Arrays, User Input Parsing, Type Casting and so on...
How - All you high level layers should throw the exception and it should be captured at the entry point and processed to understand the root cause. Usually you do this in Application_Error() where you catch the exception and log it for troubleshooting. How you log an exception is upto you. A Log File or DB driven log is an option based on your requirements and available resources.
IMO apart from extremely rare circumstances I only ever use exception handling for I/O related code where there are interactions with services and file systems whose functionality and maintenance is beyond the control of my applications.
I have always considered the use try/catch statements to manipulate the logic (flow-of-control) in a program in the same way if/else statement work to be extremely bad practice. Most common exceptions can be avoided if you use the tools at hand correctly.
Could someone explain to me why it is considered inapropriate to have a try-catch in the main() method to catch any unhandled exceptions?
[STAThread]
static void Main()
{
try
{
Application.Run(new Form1());
}
catch (Exception e)
{
MessageBox.Show("General error: " + e.ToString());
}
}
I have the understanding that this is bad practice, but not sure why.
I don't think its necessarily bad practice. There are a few caveats however...
I believe the point of whoever called this "bad practice" was to reinforce the idea that you should be catching exceptions closest to where they occur (i.e. as high up the call stack as possible/appropiate). A blanket exception handler isn't typically a good idea because its drastically reduces the control flow available to you. Coarse-grained exception handling is quite importantly not a reasonable solution to program stability. Unfortunately, many beginner developers think that it is, and take such approaches as this blanket try-catch statement.
Saying this, if you have utilised exception handling properly (in a fine-grained and task-specific manner) in the rest of your program, and handled the errors accordingly there (rather than juist displaying a generic error box), then a general try-catch for all exceptions in the Main method is probably a useful thing to have. One point to note here is that if you're reproducably getting bugs caught in this Main try-catch, then you either have a bug or something is wrong with your localised exception handling.
The primary usage of this try-catch with Main would be purely to prevent your program from crashing in very unusual circumstances, and should do hardly any more than display a (vaguely) user-friendly "fatal error" message to the user, as well as possibly logging the error somewhere and/or submitting a bug report. So to conclude: this method does have its uses, but it must be done with great care, and not for the wrong reasons.
Well, this method will only capture exceptions thrown in your main thread. If you use both the Application.ThreadException and the AppDomian.UnhandledException events instead then you'll be able to catch and log all exceptions.
I don't see how that's bad practice at all.
Letting your program crash with an unhandled exception error isn't going to instill any confidence in your end users.
Maybe someone else could provide a counter view.
Update:
Obviously you'll need to do something useful with the exception.
log it
show the user a dialog stating WHY the application is exiting (in plain text, not a stacktrace)
something else that makes sense in the context of your application.
I don't think that's a bad practice in and of itself. I think the bad practice would be if that was the ONLY try/catch block you had in your application.
In antiquity, placing a try/catch in C++ caused a fairly heavy performance penalty, and placing one around main would mean storing extra stack info for everything, which again was bad for performance.
Now computers are faster, programmers less addicted to performance, and runtimes are better built, so it's not really bad anymore (but still you might pay a little more for it, haven't benchmarked it's effect in years). So it's old folklore like iterating against the grain (compilers actually fix the iteration anyways for you nowadays). In C# it's perfectly fine, but it'd look iffy to someone from 10 years ago.
Any exception which gets to Main() is likely fatal.
If it was something easy, it should have been handled higher up. If it was something beyond your control, like OutOfMemoryException, then the program should crash.
Windows application which crash have a standard way of doing so, they trigger the Windows Error Reporting dialog. (You've likely seen it before). You can sign up to recieve crash data when this happens.
I'm not sure I think its a bad practice. What you want to do is make sure that the exception and the current state of the program when it crashes ends up in the hands of a developer, preferably logged with date, time and the user who was working with it. Basically - you want to make sure that your team has all the information they need to debug the problem, regardless of whether or not the user goes to them about the crash. Remember that many users will not, in fact, contact support if they get a crash.
The bad practice here would be catching the exception, showing a simple "Error" dialog box, and closing the application. In that case, the state of that exception is lost forever.
From a debugging standpoint, this can make life more difficult, as it makes every exception a user handled exception. This changes the debugger's behavior, unless you break on unhandled exceptions, which potentially has other issues.
That being said, I think this is a good practice at release time. In addition, I recommend listening on the AppDomain.UnhandledException and the Application.ThreadException events, as well. This will let you trap even more exceptions (such as some system exceptions that will not be caught in your "global" handler above).
That allows you to log the errors and provide the user with a good, clean message.
Change it to this and it's fine
catch(Exception ex)
{
YourLoggingSystem.LogException(ex);
}
Of course, this line should NEVER be hit as you'll have other exception handlers throughout your code catching things with much more context.
Top-level exception handling is pretty essential, but I'd recommend using:
Application.ThreadException += new ThreadExceptionEventHandler(YourExceptionHandlingMethod);
However, this will only catch exceptions on the GUI thread (much like your try..catch block) - you should use similar code for each new thread you start to handle any unexpected exceptions from them.
More about it here.
You've got the catch-all exception there which will trap everything. So if you've got any unhandled exceptions in you code you'll never see them.
On the positive side, your application will never crash!
If this is required behaviour then you'll need to have sufficient logging and reporting to let both the user and you, as developer, know what's happened and recover or exit as gracefully as possible.
I'm not saying it's bad practice, the only thing I would do different though is use the built in event for that:
Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException);
static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)
{
MessageBox.Show(e.Exception.Message); //or do whatever...
}
I think this is discouraged because exceptions are caught only once and there may be multiple things, like background threads, that need to know if a process throws.
Is this a WinForms app? Forms.Application.Run raises events whenever a thread throws an unhandled exception. The MSDN docs try to explain this, but the handler they show doesn't work! Read the updated example from the WinForms UE site.
If your program tries to keep running despite a catch-all catching who-knows-what kind of violation of assumptions down below, it's in a danger zone for things like remote exploitation of security flaws (buffer overflows, heap corruption). Putting it in a loop and continuing to run is a big red flag for software quality.
Getting out as quickly as possible is the best, e.g. exit(1). Log and exit is good though slightly riskier.
Don't believe me? The Mitre Common Weakness Enumeration (CWE) agrees. Closely related is its advice against catching NULL pointer dereferencing in this way.