다음을 통해 공유


Handle Error Gracefully

Writing error free application is difficult.

Error occurs at runtime due to unexpected user input, environment dependencies and other reasons. You must take care of all known conditions that leads the application to crash. Crashes cause user frustration and decreases your reputation.

Even though you test your applications with all the effort you can give, still you can’t guarantee the software is 100% bug free. I bet, no one can!

When you deploy Windows GUI Applications on the end users machine, you lose control. Imagine a situation when your costumer reporting you of application crash and you wish you could capture all possible reasons of the crash. Even though you can get all user inputs and corresponding actions, that might not be enough.

Fortunately windows provides a set up utilities that can gather all environmental preconditions by capturing application data for that moment in a file. That is called dump (or memory dump).

The dump is a snapshot of the application (or systems memory) that can be used later for further analysis with debugging tools like windbg or Visual Studio. While you are in the development mode you start the process inside the visual studio (F5).

Visual Studio does various steps internally to connect to the process & maps executing system instructions with your source code with help of PDB files. If you set break point, the windows waits for signal from the debugger the proceed and shows you current state of different variables. If you are advanced developer you can make use of Local windows or Watch expressions to see and manipulate the values. This is easy since the processes memory is accessible to the debugger. But when you want to check the variables state at the time user reported an error from his/her machine is not that easy. The dump files comes rescue.

Generating dump of processes running under Windows Vista and newer operating system is simple.

As right clicking on the process in Windows Task Manager and Create Dump File

image

You can also use Windows API to generate Dumps when application crashes. Because after the crash the process may not be available any longer in the task manager.

 BOOL WINAPI MiniDumpWriteDump(
  __in  HANDLE hProcess,
  __in  DWORD ProcessId,
  __in  HANDLE hFile,
  __in  MINIDUMP_TYPE DumpType,
  __in  PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
  __in  PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
  __in  PMINIDUMP_CALLBACK_INFORMATION CallbackParam
);

Equivalent C# API to call this native procedure is the following

 [DllImport("DbgHelp.dll", SetLastError = true)]
private static extern bool MiniDumpWriteDump(IntPtr hProcess, int processId, SafeHandle fileHandle, int dumpType, IntPtr excepInfo, IntPtr userInfo, IntPtr extInfo);

Windows Applications provides global error handler event, that can be used to capture any unhandled exceptions from all threads.

You can subscribe to the event by wiring a global procedure in Program class. You should do this before running any other function.

Application.ThreadException += newSystem.Threading.ThreadExceptionEventHandler(Application_ThreadException);

You may invoke MiniDumpWriteDump procedure inside Application_ThreadException function as soon as any error occurs.

This helper function would write Dump file to the system temporary directory and the user may send the error report as an email attachment or upload to your website. Also note that the procedure generates full memory dump that can be used for debugging Managed Code. Full dump file size can be larger depending on the memory usage of the executing process.

 internal static string WriteDump()
{
    using (Process process = Process.GetCurrentProcess())
    {
        string dumpFilePath = Path.Combine(Path.GetTempPath(), Application.ProductName + DateTime.Now.ToFileTimeUtc() + ".dmp");
        using (FileStream stream = new FileStream(dumpFilePath, FileMode.Create, FileAccess.ReadWrite))
        {
            Program.MiniDumpWriteDump(process.Handle, process.Id, stream.SafeFileHandle, 0x306, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
        }
        return dumpFilePath;
    }
}

Similarly in ASP.net Web Applications all unhandled exceptions can be logger from Global.asax in asp.net, similar to the following code snippet.

 void Application_Error(object sender, EventArgs e) 
{ 
    Exception ex = Server.GetLastError();
    ExceptionManager.Log(ex); //...... Log error here.
    Server.Transfer(“DefaultError.aspx”);  
}

Also in WPF Applications

 public partial class App : Application
{
    public App()
    {
        this.DispatcherUnhandledException += new DispatcherUnhandledExceptionEventHandler( App_DispatcherUnhandledException);
    }
}

You can find a sample code attached here for Handling crash and generating dump file.