Recreate stack trace with line numbers from user bug-report in .net?

后端 未结 4 1033
旧巷少年郎
旧巷少年郎 2021-01-30 15:25

First, the problem: I have several free projects, and as any software they contains bugs. Some fellow users when encounter bug send me a bug-reports with stack

相关标签:
4条回答
  • 2021-01-30 15:37

    You should use Environment.FailFast, call FailFast in the Application.UnhandledException and a dump file will be created for you.

    From the MSDN:

    The FailFast method writes a log entry to the Windows Application event log using the message parameter, creates a dump of your application, and then terminates the current process.

    Use the FailFast method instead of the Exit method to terminate your application if the state of your application is damaged beyond repair, and executing your application's try-finally blocks and finalizers will corrupt program resources. The FailFast method terminates the current process and executes any CriticalFinalizerObject objects, but does not execute any active try-finally blocks or finalizers.

    You can write a simple app that will collect the log files and send them to you.

    Now, opening the dump file is a bit tricky, Visual Studio cannot handle managed dump file (fixed in .NET 4.0) you can use WinDBG but you need to use SOS.

    0 讨论(0)
  • 2021-01-30 15:40

    You may create an application minidump whenever there is a bug and use it for offline analysis. This does not require you to deploy pdbs on the client machine. This link can serve as a good starting point for learning.

    0 讨论(0)
  • 2021-01-30 15:40

    You are absolutely on the right track of needing PDB files to accurately get source and line information. I would question any perceived issues with shipping PDB files as actually being a valid concern, but, assuming there is a valid reason, you can do this but it requires more effort on you part to create the appropriate software build environment.

    Microsoft Symbol Server will index the debug symbols and store them for use at a later date when you have a crash dump, for instance, and need symbols available. You can point either Visual Studio or Windbg at your own symbol server instance, just like Microsoft's, and it will pull down the symbols required for the debugging that version of your application (assuming you indexed the symbols with symbol server before shipping).

    Once you have the appropriate symbols for a build, you need to make sure that you have the appropriate source files that belong that build.

    This is where Microsoft Source Server comes in. Just like where Symbol Server indexes symbols, source server will index source to make sure you have the appropriate version of the source code belonging to a software build.

    Working versions of Version Control, Symbol Server and Source Server should be part of your software configuration management strategy.

    There are third party tools, some commercial, that will provide you with an API to generate application snapshots, but as you already understand, you need a mechanism for getting those snapshots uploaded to your environment somehow.

    John Robbins on PDB Files

    John Robbins on Source Server

    Check out WinDbg documentation on getting a Symbol Server up and running.

    0 讨论(0)
  • 2021-01-30 15:54

    You can get the offset of the last MSIL instruction from the Exception using System.Diagnostics.StackTrace:

    // Using System.Diagnostics
    static void Main(string[] args)
    {
        try { ThrowError(); }
        catch (Exception e)
        {
            StackTrace st = new System.Diagnostics.StackTrace(e);
            string stackTrace = "";
            foreach (StackFrame frame in st.GetFrames())
            {
                stackTrace = "at " + frame.GetMethod().Module.Name + "." + 
                    frame.GetMethod().ReflectedType.Name + "." 
                    + frame.GetMethod().Name 
                    + "  (IL offset: 0x" + frame.GetILOffset().ToString("x") + ")\n" + stackTrace;
            }
            Console.Write(stackTrace);
            Console.WriteLine("Message: " + e.Message);
        }
        Console.ReadLine();
    }
    
    static void ThrowError()
    {
        DateTime myDateTime = new DateTime();
        myDateTime = new DateTime(2000, 5555555, 1); // won't work
        Console.WriteLine(myDateTime.ToString());
    }
    

    Output:

    at ConsoleApplicationN.exe.Program.Main (IL offset: 0x7)
    at ConsoleApplicationN.exe.Program.ThrowError (IL offset: 0x1b)
    at mscorlib.dll.DateTime..ctor (IL offset: 0x9)
    at mscorlib.dll.DateTime.DateToTicks (IL offset: 0x61)
    Message: Year, Month, and Day parameters describe an un-representable DateTime.

    You can then use Reflector or ILSpy to interpret the offset:

    .method private hidebysig static void ThrowError() cil managed
    {
        .maxstack 4
        .locals init (
            [0] valuetype [mscorlib]System.DateTime myDateTime)
        L_0000: nop 
        L_0001: ldloca.s myDateTime
        L_0003: initobj [mscorlib]System.DateTime
        L_0009: ldloca.s myDateTime
        L_000b: ldc.i4 0x7d0
        L_0010: ldc.i4 0x54c563
        L_0015: ldc.i4.1 
        L_0016: call instance void [mscorlib]System.DateTime::.ctor(int32, int32, int32)
        L_001b: nop 
        L_001c: ldloca.s myDateTime
        L_001e: constrained [mscorlib]System.DateTime
        L_0024: callvirt instance string [mscorlib]System.Object::ToString()
        L_0029: call void [mscorlib]System.Console::WriteLine(string)
        L_002e: nop 
        L_002f: ret 
    }
    

    You know that the instruction before 0x1b threw the exception. It's easy to find the C# code for that:

     myDateTime = new DateTime(2000, 5555555, 1);
    

    You could map the IL code to your C# code now, but I think the gain would be too little and the effort too big (though there might be a reflector plugin). You should be fine with the IL offset.

    0 讨论(0)
提交回复
热议问题