C# unhandled exception handler, attempting to write to log file
My application is a Windows Forms .NET 4 C# TCP/IP server. It has been crashing about once per day with a generic Windows Server crash message (press close to close this application)开发者_如何学C. I inserted the following code to catch any exception that might be causing this, and I inserted a simple null Object into a routine that gets called regularly to generate a test exception.
Two things:
- When the test exception occurs, the log code is hit in the debugger, the file is created and written to, and everything is fine.
- Without the debugger, I get a "continue or quit" .NET stacktrace message, and regardless of which I select, the file is never created or written to.
The .NET message is useless to me. I need a logfile stack trace of the crash. Does anyone know how I can do this? Thanks.
static class Program
{
[STAThread]
static void Main(string[] rgszArgs)
{
//My exception handler
AppDomain.CurrentDomain.UnhandledException +=
new UnhandledExceptionEventHandler(CatchUnhandledException);
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new FormMain(rgszArgs));
}
static void CatchUnhandledException
(object sender, UnhandledExceptionEventArgs e)
{
StreamWriter sw;
DateTime dtLogFileCreated = DateTime.Now;
Exception ex;
try
{
sw = new StreamWriter("crash-" + dtLogFileCreated.Day + dtLogFileCreated.Month
+ dtLogFileCreated.Year + "-" + dtLogFileCreated.Second
+ dtLogFileCreated.Minute + dtLogFileCreated.Hour + ".txt");
ex = (Exception)e.ExceptionObject;
sw.WriteLine("### Server Crash ###");
sw.WriteLine(ex.Message + ex.StackTrace);
sw.Close();
}
finally
{
Application.Exit();
}
}
}
You want the Application.ThreadException event.
The AppDomain unandled exception event capturess unhandled exceptions thrown - for example any exceptions thrown by the Main
method, however Application.Run
handles exceptions internally - this means that Application.Run
won't throw an exception as a result of an exception in an event handler, and so CatchUnhandledException
is never run.
This means that if the ThreadException
handler was able to recover from the exception the application will continue running normally (if the exception was thrown by Application.Run
there would be no chance of recovery). For reasons that I don't understand this behaviour is different when debugging.. When debugging this behaviour is changed so that the exception is thrown allowing you to debug the exceptions immediately in Visual Studio - this is why your unhandled exception handler is working while debugging.
Note that the above CatchUnhandledException
handler will catch exceptions thrown by background threads in your app domain.
See also Application.SetUnhandledExceptionMode.
I have to guess this is an event handler for the AppDomain.UnhandledException event. One thing you definitely cannot do is call Application.Exit(), the program is no longer in the right state to close down nicely, you have to call Environment.Exit(). The Application.Exit() call is the likely source of the "continue or quit" message, that sounds like the ThreadExceptionDialog that a Winforms app displays with it suffers a hearth attack in the UI thread.
The next problem is the argument you pass to the StreamWriter constructor. You don't specify a full path name for the file (like c:\mumble\foo.txt), it might try to write the file to a directory where you don't have write access. Very likely on Vista or Win7. Or the file actually got written but you just can't find it back because you don't know where to look.
Use Environment.GetFolderPath() to pick a directory that you know you can write to.
This is from MSDN on AppDomain.UnhandledException Event:
Starting with the .NET Framework version 4, this event is not raised for exceptions that corrupt the state of the process, such as stack overflows or access violations, unless the event handler is security-critical and has the HandleProcessCorruptedStateExceptionsAttribute attribute.
Could this be it?
You could also try making a call to Environment.FailFast("reason for failure here"
) if the state of your program is in such disarray that any code in a try/finally block would corrupt your program. This will write to the event log automatically.
精彩评论