Displaying and capturing c# exceptions - c#

I have a c# program which throws a NullReferenceException(). When I start this on my Vista machine, it gives the familiar screen "Foo has stopped working". I can easily click on 'details' to see what went wrong. On one XP machine there's no warning at all: the program just quits, and on another XP I get the "Foo has encountered a problem..." message. Is there a way I can change this (XP's) setting?
Furthermore, I would like to have this error message written to a log file, so I can see what went wrong if somebody else uses my program. Is there a way I can send the uncaught exceptions to a file?
edit: I want this for my entire project, not just for a critical section. I didn't think it is recommended practice to wrap the entire program in a big try...catch, or is it?

Take a look at : UnhandledException and ThreadException.
You may log the errors in a file, or use Windows logging facilities.
You may also try this and this, it should point you in the direction you want to go. It's a post about the exact same problem you are trying to solve.

If you're targeting WPF, you can use the DispatcherUnhandledException to catch any exception that you don't handle in code. Otherwise, make sure to catch any foreseeable exception with try-catch blocks.
Either in DispatcherUnhandledException's delegate or in the catch section of a try-catch block, you can then call a function that writes the error message to a log file.

Add try catch blocks around all components that you think will fail and handle these by streaming the error data to your log file

See this link:
http://blogs.msdn.com/csharpfaq/archive/2006/03/27/562555.aspx
This will get you up and running.
Use:
try
{
// Your code here
}
catch (Exception ex)
{
// This will tell you the Exception
Console.WriteLine("Exception type: {0}", ex.GetType());
// or, if you use the example from the link above
LogMessageToFile(String.Format("Exception type: {0}", ex.GetType));
}

You could wrap up your code in a
try
{
// Your code
}
catch (Exception ex)
{
streamWriter.WriteLine("your custom exception text, stack trace:" + ex.StackTrace.ToString());
MessageBox.Show("Your custom exception text, Stack Trace:" + ex.StackTrace.ToString());
}
and handle the feedback yourself with a stream writer object pointing to a log file of your chosing.
If its a winforms app you could include a message box or custom dialogue informing the user of what happened as shown above.

Related

Log4net not logging exception

I have log4net successfully setup for my C# application. Everything works fine, except when I do this:
catch (Exception ex)
{
if (log.IsErrorEnabled)
log.Error("test", ex);
}
All I get is the message "test", I do not get the exception at all. Then, when I do this:
catch (Exception ex)
{
if (log.IsErrorEnabled)
log.Error(ex);
}
I get the exception as desired, stack trace and everything. This works, but ideally I'd like to have both the message and the exception.
Why does the exact same code (no configuration changes) not work in the first example but it does in the second example? Am I reading the docs wrong for the Error() method?
The first overload you are using is the one that you want: Error(string, Exception). If the exception is actually written depends on your appender and / or the layout you choose. Here is explained how to disable printing of the stacktrace: https://stackoverflow.com/a/3660529/106567
I need to see your configuration in order to tell why the exception is not printed.
The code that "works" is not really what you should do: log.Error(ex) seems to do what you want since log4net treats the exception as the message object and simply calls toString() on it. Any appender / layout that specifically deals with exceptions would be unable to process the exception properly. The same happens if you use one of the ErrorFormat overloads (actually I never quite understood, why you cannot use a formatted string and an exception at the same time).
The solution was not relevant in the code I posted, but I was not fixing the flags correctly. The eventual solution was already found in this stack overflow post
Try
log.ErrorFormat("test: {0}", ex);

How do I find the exception type of an exception that gets thrown in C#?

I am using a library that doesn't seem to document the exceptions. This library is used to communicate with a product the company makes. I want to be able to differentiate between the exceptions that get thrown but I don't know the names of the exceptions (for example between a communication timeout or under-voltage condition).
All of their examples only use catch(Exception ex). How can can I find what I need to use to catch the individual errors? When I do ex.toString() I get something like this:
System.Exception: Timeout
at CMLCOMLib.EcatObj.Initialize()
at copley_cmo_test.MainWindow.btnConnect_Click(Object sender, RoutedEventArgs e)
in c:\Users\adam.siembida\Desktop\copley_cmo_test\copley_cmo_test\MainWindow.xaml.cs:line 41
This:
System.Exception: Timeout
shows that they're just throwing a bare System.Exception, e.g.
if (weHaveNoApiDesignSkills)
{
throw new Exception("Timeout");
}
It's possible that there are some exceptions which are better designed, but the one you've shown isn't promising :(
Unfortunately unless you start using the message in the exception to differentiate between them (which is almost always a bad idea) you're stuck. It may be worth asking the authors of the library to see if they can improve matters for a future release.
Catch it with a catch-all construct such as catch(Exception ex), then examine the Type returned by ex.GetType(). If it's equal to typeof(Exception), it means that they aren't throwing anything more specific than Exception.
By the way, if you're stopped when the exception has been caught (ie, in a catch block), if you enter $exception in the watch window, you will see the entire exception.
When the API in library which you are using is not documented properly , you should catch the base exception and log it not only by the message instead whole exception by converting the exception to string . Eg.
try
{
//api call which throws exception.
}
catch(Exception ex)
{
//log ex.ToString();
}
use a decompiler for example:
http://www.jetbrains.com/decompiler/
in .net there's no explicit exception declaration like in java so as i see it it's the only way.

Problems with entity framework

I'm having problems working with EntityFramework. While below peace of code works fine on my PC, when it's transported to a VPS (with everything properly preinstalled), it gives me a Unhandled Exception: System.NullReferenceException: Object reference not set to an instance of an object, but the message box that is supposed to catch this does not show up. Any suggestions?
Thank you in advance.
var cc = new CopierContext();
try
{
MessageBox.Show(cc.Database.Connection.ConnectionString.ToString());
var matchingProviders2 = cc.Providers.Where(prov => prov.Login == "batman");
}
catch (Exception e)
{
MessageBox.Show(e.InnerException.Message);
}
Update:
I finally got to the core of the problem. The reason is: I've had .NET 4 on VPS, while application was developed using .NET 4.5. Installing the latter one removed all problems. Thank you for all your help.
I don't know how you are running it on your VPS, but if it is not launched under the interactive user account, your message boxes will not show up.
Well from the docs on the Exception.InnerException Property
The InnerException property returns the same value as was passed into
the constructor, or a null reference
Since you're catching any old exception catch (Exception e) its quite possible that the exception that's being thrown isn't the exception you were expecting and doesn't have a InnerException. This means your catch block may be raising an exception.
There are several actions you could take.
Do not catch System.Exception exception in anything but a top level exception handler. Only catch exceptions you know what to do with. Which leads to...
Set up a top level exception handler
Finally when logging or displaying exception messages at least make sure you have an inner exception before you try and use it.
MessageBox.Show( (e.InnerException != null ? e.InnerException : e).Message );
Don't use a MessageBox as it is a service; log them to disk instead such that you can recall them, or perhaps automatically mail them to you such that you are up to date on problems occuring.
You will also want to add e.InnerException.StackTrace to the log.
My bet is that you did not configure something (or did not configure it correctly) and cc.Database.Connection.ConnectionString is null. Calling .ToString() causes the NullReferenceException. That's why you don't see the message box. As other people said - using MessageBox for this kind of debugging is not a good idea. In the catch you should print not message but e.ToString() it will show the stack trace that should point to the place where the problem is.

Getting exception that caused program to crash without being in debug mode

I have an application in C# that I want to run by just running the .exe from my desktop. However, I'm pretty sure there will be some type of error that will make the program crash. Is there a way to write the problem that caused the program to crash to a text file, so that I can see what caused the issue when users are using the program? I know I can use debug mode to do this but I want to run the application as a stand alone not inside of VS.
Thanks,
I am aware of the try catch blocks and I am already using those where problems might occur. But I am speaking in general. For example if I wasn't sure where the problem would occur. There is no way to print this specific error to a file.
You can try the global try/catch method except that if there is an exception on a background thread it won't be caught. You can use AppDomain.UnhandledException if you want to be notified of any unhandled exception in the appdomain (msdn). You would signup in main before the rest of your program executes like so:
static void Main(string[] args)
{
AppDomain.UnhandledException += WriteUnhandledExceptionToFile;
// rest of program
}
static void WriteUnhandledExceptionToFile(object sender, UnhandledExceptionEventArgs args)
{
// write to where ever you can get it.
string path = Path.Combine(Environment.CurrentDirectory, "UnhandledException.txt");
File.WriteAllText(path, args.ExceptionObject.ToString()); // will print message and full stack trace.
}
Edit
Note that by default Windows Forms and WPF catch any exceptions that are thrown on the UI thread. You will have to subscribe to the Application.ThreadException event (forms) or Application.DispatcherUnhandledException event (wpf) to be notified of exceptions on those threads. The code would be very similar to the code above for the AppDomain event.
Have a global exception handler that writes the exception details to a file.
If you wrap the code in your Main method in a try{}catch{} block, you can write out the exception details in the catch block.
try
{
// Calls to application code
}
catch(Exception ex)
{
// log `ex.ToString()`
throw; // rethrow to ensure termination optionally: `Application.Exit`
}
Even if you aren't logging the problem, you can usually get the error in question from the event viewer within windows.
The first thing you want to look at is the try/catch construct in C#. This is probably your first building block to handling errors.
As for how you handle the errors, that's entirely up to you. Currently your only stated goal is to log them to a file. You can get a lot of details out of the Exception object that you catch and you can write those details to a file. Additionally, you can use logging libraries to help with that sort of thing.
Proper error handling is something of a big subject, really. One thing to keep in mind is logically where you want to catch the exception. Ideally, you want to catch it where you can handle it. That is, where your code can sufficiently recover from the error. If it's a fatal error and the application should stop entirely, then you can throw the exception further up the stack and let it go unhandled (though still logged where you caught it).
If, however, you're in a logical condition where you can just log the error and move on, then the catch block allows you to do just that. Log the details, update the state of any objects/data which need to be updated, and continue with the flow of the application.
you can surround your one of the starting method with try catch block
try
{
///Your code
}
catch(Exception exception)
{
System.IO.File.WriteAllLines("ErrLog.txt", exception.Message);
}
As a permanent solution you can create extension method ToLog and use it whenever you want.
public static void ToLog(this Exception Exception)
{
using (var file = File.AppendText("ErrorLog.txt"))
{
file.WriteLine(DateTime.Now + " : " + exception.Message);
}
}
You can use it in catch block like this
catch(Exception exception)
{
exception.ToLog();
}
See initial information here http://www.csharp-examples.net/catching-unhandled-exceptions/
static void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
{
MessageBox.Show(e.Exception.Message, "Unhandled Thread Exception");
}
static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
MessageBox.Show((e.ExceptionObject as Exception).Message, "Unhandled UI Exception");
}
The UnhandledException event handles uncaught exceptions thrown from the main UI thread. The ThreadException event handles uncaught exceptions thrown from non-UI threads.
I would replace the MessageBox with some actual logging (log4net or others). This would give you the ability to log out the errors to another server for distributed applications, file system for local users, event logs, options are fairly unlimited if you're willing to put in the time.

How to log exceptions in Windows Forms Application

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!

Categories

Resources