David Ong
David Ong

Reputation: 117

WPF Program Startup Crash: How to Debug?

I have a WPF program that runs fine on the development PC and on the client PC 1. But on client PC 2, it crashes immediately on startup with the Send Report to Microsoft window. I would appreciate some advice on how to trace what is wrong. Here's what I have tried:

  1. Inserted try-catch in my main window class:

    public MainWindow()
    {
      try
      {
         MessageBox.Show("Before InitComp()");
         InitializeComponent();
         MessageBox.Show("Before Sub1()");
         Subroutine1();
         MessageBox.Show("Before Sub2()");
         Subroutine2();
         ... etc ...
      }
      catch (Exception ex)
      {  ... code for MessageBox display error here ... }
    }
    

The idea is to try to isolate which part of the startup sequence is crashing, but the first debug message "Before InitComp()" does not even show up. So it seems the app is crashing even before starting my code.

  1. One possibility is to install the entire VS2008 in the client PC 2, load in the source and use the IDE Debugger to trace the problem. This is likely the most effective in finding the problem. But I do not want to do this because a) the client PC 2 does not belong to me, b) it does not scale: I must do likewise for client PC 3/4/5/... and c) it violates my firm's VS2008 license.

How should I go about debugging this problem?

Upvotes: 7

Views: 7691

Answers (4)

Jeffrey Knight
Jeffrey Knight

Reputation: 5977

In your App.xaml header, add:

<Application DispatcherUnhandledException="App_DispatcherUnhandledException" />

and in your App.xaml.cs, add something like:

    void App_DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs args)
    {
        log.Fatal("An unexpected application exception occurred", args.Exception);

        MessageBox.Show("An unexpected exception has occurred. Shutting down the application. Please check the log file for more details.");

        // Prevent default unhandled exception processing
        args.Handled = true;

        Environment.Exit(0);
    }

Upvotes: 8

J Trana
J Trana

Reputation: 2190

Old school approach: A hard crash like that is probably bubbling out to something you can see via Event Viewer in Windows. Have you checked there yet? A lot of times this tells me the answer without any extra trouble.

Upvotes: 7

bryanmac
bryanmac

Reputation: 39296

Tracing/Logging is very powerful especially when the problem is happening with a customer. You can't always debug and a dump may not provide the full view to what led up to that point. It definately compliments a dump or debugging.

You can also turn it on and off and even switch levels.

DebugView is a good program to capture traces:

http://technet.microsoft.com/en-us/sysinternals/bb896647

Tracing:

http://msdn.microsoft.com/en-us/library/3at424ac.aspx

For example, here's a sample trace class with switchable levels:

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Diagnostics;
using System.Globalization;
using System.Threading;

namespace Sample
{
    public class Tracer
    {
        //
        // supports holding many trace switches.
        //
        static Dictionary<string, TraceSwitch> s_switches = new Dictionary<string, TraceSwitch>();
        static TraceSwitch s_switch = new TraceSwitch("trace", "Default tracing switch");
        static object s_locker = new object();

        private static TraceSwitch GetSwitch (string category)
        {
            // only pay the lock penalty if it doesn't exist
            if (!s_switches.ContainsKey (category))
            {
                lock (s_locker)
                {
                    if (!s_switches.ContainsKey (category))
                    {
                        TraceSwitch traceSwitch = new TraceSwitch(category,
                                    String.Format("Tracing switch for category '{0}'", category));
                        s_switches.Add (category, traceSwitch);
                    }
                }
            }

            return s_switches[category];
        }

        //
        // No level overloads
        //
        public static void Output(string message)
        {
            WriteLine("None", TraceLevel.Info, message);
        }

        public static void OutputIf(bool condition, string message)
        {
            if (condition)
            {
                Output(message);
            }
        }

        public static void Output(string format, params object[] args)
        {
            Debug.Assert(format != null);
            Output(string.Format(CultureInfo.InvariantCulture, format, args));
        }

        public static void OutputIf(bool condition, string format, params object[] args)
        {
            if (condition)
            {
                Output(format, args);
            }
        }

        //
        // Error level overloads
        //
        public static void Error(string message)
        {
            if (s_switch.TraceError)
            {
                WriteLine(String.Empty, TraceLevel.Error, message);
            }
        }

        public static void Error(string category, string message)
        {
            if (GetSwitch(category).TraceError)
            {
                WriteLine(category, TraceLevel.Error, message);
            }
        }

        public static void ErrorIf(bool condition, string message)
        {
            if (condition)
            {
                Error(message);
            }
        }

        public static void ErrorIf(string category, bool condition, string message)
        {
            if (condition)
            {
                Error(category, message);
            }
        }

        public static void Error(string format, params object[] args)
        {
            Debug.Assert(format != null);
            Error(string.Format(CultureInfo.InvariantCulture, format, args));
        }

        public static void Error(string category, string format, params object[] args)
        {
            Debug.Assert(format != null);
            Error(category, string.Format(CultureInfo.InvariantCulture, format, args));
        }

        public static void ErrorIf(bool condition, string format, params object[] args)
        {
            if (condition)
            {
                Error(format, args);
            }
        }

        public static void ErrorIf(string category,
                                   bool condition,
                                   string format,
                                   params object[] args)
        {
            if (condition)
            {
                Error(category, format, args);
            }
        }

        //
        // Warning level overloads
        //
        public static void Warning(string message)
        {
            if (s_switch.TraceWarning)
            {
                WriteLine(String.Empty, TraceLevel.Warning, message);
            }
        }

        public static void Warning(string category, string message)
        {
            if (GetSwitch(category).TraceWarning)
            {
                WriteLine(category, TraceLevel.Warning, message);
            }
        }

        public static void WarningIf(bool condition, string message)
        {
            if (condition)
            {
                Warning(message);
            }
        }

        public static void WarningIf(string category, bool condition, string message)
        {
            if (condition)
            {
                Warning(category, message);
            }
        }

        public static void Warning(string format, params object[] args)
        {
            Debug.Assert(format != null);
            Warning(string.Format(CultureInfo.InvariantCulture, format, args));
        }

        public static void Warning(string category, string format, params object[] args)
        {
            Debug.Assert(format != null);
            Warning(category, string.Format(CultureInfo.InvariantCulture, format, args));
        }

        public static void WarningIf(bool condition, string format, params object[] args)
        {
            if (condition)
            {
                Warning(format, args);
            }
        }

        public static void WarningIf(string category,
                                     bool condition,
                                     string format,
                                     params object[] args)
        {
            if (condition)
            {
                Warning(category, format, args);
            }
        }

        //
        // Info level overloads
        //
        public static void Info(string message)
        {
            if (s_switch.TraceInfo)
            {
                WriteLine(String.Empty, TraceLevel.Info, message);
            }
        }

        public static void Info(string category, string message)
        {
            if (GetSwitch(category).TraceInfo)
            {
                WriteLine(category, TraceLevel.Info, message);
            }
        }

        public static void InfoIf(bool condition, string message)
        {
            if (condition)
            {
                Info(message);
            }
        }

        public static void InfoIf(string category, bool condition, string message)
        {
            if (condition)
            {
                Info(category, message);
            }
        }

        public static void Info(string format, params object[] args)
        {
            Debug.Assert(format != null);
            Info(string.Format(CultureInfo.InvariantCulture, format, args));
        }

        public static void Info(string category, string format, params object[] args)
        {
            Debug.Assert(format != null);
            Info(category, string.Format(CultureInfo.InvariantCulture, format, args));
        }

        public static void InfoIf(bool condition, string format, params object[] args)
        {
            if (condition)
            {
                Info(format, args);
            }
        }

        public static void InfoIf(string category,
                                  bool condition,
                                  string format,
                                  params object[] args)
        {
            if (condition)
            {
                Info(category, format, args);
            }
        }

        //
        // Verbose level overloads
        //
        public static void Verbose(string message)
        {
            try
            {
                if (s_switch.TraceVerbose)
                {
                    WriteLine(String.Empty, TraceLevel.Verbose, message);
                }
            }catch{}
        }

        public static void Verbose(string category, string message)
        {
            if (GetSwitch(category).TraceVerbose)
            {
                WriteLine(category, TraceLevel.Verbose, message);
            }
        }

        public static void VerboseIf(bool condition, string message)
        {
            if (condition)
            {
                Verbose(message);
            }
        }

        public static void VerboseIf(string category, bool condition, string message)
        {
            if (condition)
            {
                Verbose(category, message);
            }
        }

        public static void Verbose(string format, params object[] args)
        {
            Debug.Assert(format != null);
            Verbose(string.Format(CultureInfo.InvariantCulture, format, args));
        }

        public static void Verbose(string category, string format, params object[] args)
        {
            Debug.Assert(format != null);
            Verbose(category, string.Format(CultureInfo.InvariantCulture, format, args));
        }

        public static void VerboseIf(bool condition, string format, params object[] args)
        {
            if (condition)
            {
                Verbose(format, args);
            }
        }

        public static void VerboseIf(string category,
                                     bool condition,
                                     string format,
                                     params object[] args)
        {
            if (condition)
            {
                Verbose(category, format, args);
            }
        }

        //
        // Trace Output Format:
        // [category:level]PID|ThreadID|08:16:15.134| message.
        //
        private static void WriteLine(string category,
                                      System.Diagnostics.TraceLevel level,
                                      string message)
        {
            Debug.Assert(message != null);

            string traceLine = string.Format(
                CultureInfo.InvariantCulture,
                "[{0}:{1}]{2}|{3}|{4:HH}:{4:mm}:{4:ss}.{4:fff}|{5}",
                category,
                level.ToString(),
                Process.GetCurrentProcess().Id,
                Thread.CurrentThread.ManagedThreadId,
                DateTime.Now,
                message);

            Trace.WriteLine(traceLine);
        }
    }
}

Upvotes: 1

Ilian
Ilian

Reputation: 5355

Download ProcDump. Run procdump -t -w app.exe ... or possibly procdump -e -w app.exe .... Explore other flags as well. Then open the dump file in your favorite debugger (Visual Studio/WinDbg) and look at stack trace.

Upvotes: 2

Related Questions