I am investigating some crashes in my application caused by a Win32 exception, and I have narrowed it down that it must be occurring in the threadpool which is taking care of the EventLog.EntryWrittenEventHandler event handler in my application. I set this up like this:
// Create the event log monitor
eventLog.Log = "Application";
eventLog.EnableRaisingEvents = true;
eventLog.EntryWritten += new EntryWrittenEventHandler(EventLogMonitor);
EventLogMonitor is the handler for my event. I am wondering does anybody have any ideas as to where I could find out whats causing this exception. It seems that to listen for events a ThreadPoolWaitOrTimerCallback is being set up, which wouldn't have any of my code on it, and if the exception is occurring on this I just cant see how to deal with this problem. Any help is really appreciated!!
Here is the output of !clrstack in WinDBG:
0:008> !clrstack
OS Thread Id: 0x106c (8)
ESP EIP
049df1c8 7756f871 [HelperMethodFrame: 049df1c8]
049df26c 73ce6fa0 System.Diagnostics.EventLog.get_OldestEntryNumber()
049df27c 73bf24ed System.Diagnostics.EventLog.CompletionCallback(System.Object)
049df2c4 73bf0fe4 System.Diagnostics.EventLog.StaticCompletionCallback(System.Object, Boolean)
049df2f4 744fc3b8 System.Threading._ThreadPoolWaitOrTimerCallback.WaitOrTimerCallback_Context(System.Object, Boolean)
049df300 744fc373 System.Threading._ThreadPoolWaitOrTimerCallback.WaitOrTimerCallback_Context_f(System.Object)
049df304 7400027f System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)
049df31c 744fc477 System.Threading._ThreadPoolWaitOrTimerCallback.PerformWaitOrTimerCallback(System.Object, Boolean)
049df4ac 74991b5c [GCFrame: 049df4ac]
In case it helps, my application is just checking the event ID of every entry written to the event log, and if it matches one of a certain set of ID's then I log it. The crashes happen quiet rarely, and the exception is a System.ComponentModel.Win32 exception with message 'Access is denied'. That sounds like it could be a permissions issue but why would it work ok for a certain period and then suddenly crash with this.
If I understand you correctly (it would help if you pass the stacktrace that leads you to the conclusion that the exception is happening inside a threadpool thread), then just wrap your code of EventLogMonitor in a try/catch block.
Example:
void EventLogHandler(object sender, EventArgs args)
{
try
{
// Your original code.
}
catch (Exception ex)
{
// Log or Write "ex" to the console. Set a breakpoint, whatever.
throw;
}
}
UPDATE: after your update it looks as if the exception is indeed not raised from inside your handler, but before it is even called inside the EventLog class.
You could try registering a handler with the AppDomain.UnhandledException event and do your logging/handling in there. Note that this will not allow you to suppress or "change" or wrap the exception, but merely to log it somewhere for diagnostic purposes.
If you just want to inspect the exception once (or on occasion), you should try using the SOS-extension's !PrintException command in WinDBG.
UPDATE 2: after further investigation I find it rather strange that the exception bubbles up all. Your stacktrace suggests you're using .NET 3.5 (or earlier, but not 4.) and looking at the EventLog class in Reflector you can see that the whole handling of the EventWrittenHandler, including the preamble code that seems to cause the exception, is wrapped in one big "try/catch(Exception)/catch" block. Funny.
Subscribe to Application.ThreadException in your Program.cs as follows to be able to catch the exceptions that are not in main thread.
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.ThreadException += Application_ThreadException;
try
{
Application.Run(new MainForm());
}
catch (Exception e)
{
HandleException(e);
}
}
static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)
{
HandleException(e.Exception);
}
If you can, use Tasks in System.Threading.Tasks.
Try, where action is performing what you want.
ThreadPool.QueueUserWorkItem(state =>
{
try
{
action();
}
catch (Exception ex)
{
OnException(ex);
}
});
Not sure what kind of Application this is, so in a general case, if you're having no luck, try hooking into the AppDomain in which the code is running. If you don't have multiple domains, you can try:
AppDomain.CurrentDomain.FirstChanceException += Handler
or
AppDomain.CurrentDomain.UnhandledException += Handler
Related
After reading this MSDN page, I've created a global exception handler in my .net class library, for logging purposes, which looks like this:
static void OnException(object sender, UnhandledExceptionEventArgs args)
{
Exception ex = (Exception)args.ExceptionObject;
Logging.LogException(ex);
}
But then if I throw new UnauthorizedAccessException() or throw new Exception() from a method, this does not catch it at all.
The MSDN page says:
UnhandledExceptionEventArgs provides access to the exception object
and a flag indicating whether the common language runtime is
terminating. The UnhandledExceptionEventArgs is one of the parameters
passed into UnhandledExceptionEventHandler for the
AppDomain.UnhandledException event
I believe what I'm doing falls under the AppDomain (and not ThreadException)? What am I doing wrong here?
PS. I'm trying to avoid a try-catch block, since apparently it's bad practice. This class library is called from a windows service which runs periodically so I'd rather not let it 'crash' to avoid memory leaks due to unforeseen exceptions and would prefer to monitor the event logs regularly.
You will need to install the exception handler in the current app domain in order for it to fire:
AppDomain.CurrentDomain.UnhandledException += OnException;
Otherwise its just a method declaration that will never be called.
You mention that you are trying to avoid a try catch, but inside your handler, that wouldn't be a bad idea:
static void OnException(object sender, UnhandledExceptionEventArgs args)
{
try
{
Exception ex = (Exception)args.ExceptionObject;
Logging.LogException(ex);
}
catch
{
// do nothing to silently swallow error, or try something else...
}
}
...Because you don't want to explode in your error handler. Either swallow if stability is of primary importance, or try a secondary (more basic) logging method to insure that no exception falls through the cracks.
Normally, swallowing an exception silently is a poor practice, but this is inside an error handling block where failure means crashing an app.
I am testing exception handling in my .NET application. With code below, I can log all exceptions, but I don't know how to catch them, so they are not stopping my application.
Here's the code I am using:
public class ExceptionHandler
{
public ExceptionHandler()
{
AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.FirstChanceException += MyHandler2;
}
private void MyHandler2(object sender, FirstChanceExceptionEventArgs e)
{
try
{
throw e.Exception;
//this ends up in eternal loop with 'stack overflow'
}
catch (Exception exception)
{
//exception never comes here, but if the exception is
//not caught inside catch block, then it's unhandled and it stops application
}
}
}
So, how can I catch the exception e in MyHandler2 ? I can't use only catch, it must be try - catch ...
Well, of course it is not getting to the catch clause. Unintentionally, you have created a recursion:
First chance exception occurred somewhere in your program.
You handler is being triggered.
There is a first chance exception in your handler, woops! better go to my exception handler!
You handler is being triggered.
There is a first chance exception in your handler, woops! better go to my exception handler!
You handler is being triggered.
There is a first chance exception in your handler, woops! better go to my exception handler!
You handler is being triggered.
There is a first chance exception in your handler, woops! better go to my exception handler!
...
and there is your stack overflow...
As #Marc Gravell pointed out in his answer, this event is not for handling exceptions. Exceptions should be handled locally.
Take a look at this SO thread for more details.
You can't suppress exceptions in the way you are trying; this is just an opportunity to do things like logging; from MSDN:
This event is only a notification. Handling this event does not handle the exception or affect subsequent exception handling in any way.
Why do you want to throw exception again? just work on e.Exception in MyHandler2.
FirstChanceException Handler will take it before CLR and thus it will never reach to Catch block in MyHandler2 and will again call MyHandler2 and thus it will become recursive and end up in StackOverflow.
As explained by Mark:
This event is only a notification. Handling this event does not handle the exception or affect subsequent exception handling in any way.
Following is the only way to catch(get notified) it:
private void MyHandler2(object sender, FirstChanceExceptionEventArgs e)
{
//Never throw here
//throw e.Exception;
GetNotified(e.Exception);
}
Here GetNotified is a method where you can log error or send notifications (everything except throwing error).
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.
I tried to write a little crash reporter for uncatched expetions. This works perfectly when starting my App in VS.
But as soon as I try to start the .exe it only shows me the standard "There is an uncaught expetion"-thingy from windows.
And no it's not the crashreporter which crashes.
This is my code in the Program.cs
try
{
Application.Run(new TestServer());
}
catch (Exception e)
{
Application.Run(new CrashReporter(e.StackTrace.ToString()));
}
}
This is because you use a debugger. Winforms detects this and disables the event handler for Application.ThreadException. That's important, it lets you debug exceptions. To get your catch clause to work without a debugger, you'll have to add this statement to your Main() method, before the Run() call:
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.ThrowException);
It now does make more sense to write an event handler for AppDomain.Current.UnhandledException instead, you'll also get notified about unhandled exceptions in worker threads.
Instead of this you can handle following event (which is the preferred way of handling unhandled application exceptions):
AppDomain.CurrentDomain.UnhandledException += (sender, e) =>
{
Application.Run(new CrashReporter(e.StackTrace.ToString()));
}
Application.Run(new TestServer());
Are you running on a 64 bit OS? This sounds like the problem Hans Passant answered here.
Debugging can swallow errors on Form construction and Forms_Load in 64 bit CLR...
Are you sure this thing works? I mean, did this strategy work for you previously?
I use (and suggested way) this way to catch the unhandled exceptions globally:
AppDomain.CurrentDomain.UnhandledException +=
new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
//then start the main form...
Application.Run(new TestServer());
Here is the documentation
http://msdn.microsoft.com/en-us/library/system.appdomain.unhandledexception.aspx
CrashReporter is causing it. An uncaught exception in a catch statement will cause an uncaught exception. You need another try/catch in your catch and another fall back.
I have an app, and after about 20 minutes of idle time the program just crashes. ("Windows has encountered an error and needs to close...")
I have no idea why this is happening. What is the best way to go about debugging something like this?
Generally crashes in .Net applications are caused by an unhandled exception - i.e. an exception in a thread in that application that was not caught in a try-catch block of some sort:
try
{
// Some code that may throw an exception
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
A good first place to check for information about this exception is the application event log, often however you will find that the .Net framework posts only minimal information about the crash - if this is the case then you need to catch and handle the exception yourself, recording enough information to allow you to diagnose the error.
Typically there are two way that you might do this:
1. Ensure that the code for each thread of your application is contained in a try-catch block.
This is the easiest method - unless your application has multiple user threads (you will know if it has), this simply requires that you place a try-catch block around the entry point of your application, for example in a Windows Forms application:
// Probably found somewhere in Program.cs
[STAThread]
static void Main()
{
try
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
If you are working on a console application then you will need to use something other than MessageBox (see the first example).
If you spawn multiple threads then the entry point method for each thread should also catch all exceptions in a similar way.
2. Handle the UnhandledException event of the current App Domain
This event will be fired whenever any thread throws an unhandled exception in the current App Domain. Generally speaking it is best to use the first method instead, however this event is still useful in some situations.
Example:
static void Main()
{
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
// The rest of your application
}
static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
Console.WriteLine(e.ExceptionObject.ToString());
}
Of course it is worth pointing out that the error still might not be caught by either of the above two methods (which is possible if the error is caused by a native module loaded in the same process), however this should probably do the trick.
Finally - Good luck!