简体   繁体   中英

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). 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:

  1. When the test exception occurs, the log code is hit in the debugger, the file is created and written to, and everything is fine.
  2. 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM