Generate / create mdump files for in my app

前端 未结 2 2038
天命终不由人
天命终不由人 2021-02-04 15:28

Im looking for a way to generate minidump files in my applications simular to what ProcDump does but prefarably with code and not having to extract a 3dparty tool to do it.

2条回答
  •  被撕碎了的回忆
    2021-02-04 16:33

    So there is one solution that comes to mind and meets the following goals:

    • Size of the binary would increase by around 300k
    • Ability to generate mdump files in a fatale crash.
    • Ability to do "pause" the app do a dump, and contiune would be a bonus

    I'll give this requirement a complete unknown:

    • No way i can port that app to run inn windows mobile.

    So what's the solution?

    Integrate the required parts you need from the Microsoft Sample for MDbg.exe to provide you with a 'just-in-time' debugger that attaches, dumps, and detaches from the crashing process.

    Step 1 - Start by downloading the source code to the mdbg from here: http://www.microsoft.com/downloads/en/details.aspx?FamilyID=38449a42-6b7a-4e28-80ce-c55645ab1310&DisplayLang=en

    Step 2 - Create a 'crash' handler that spawns a debugger process and waits for completion. I used the following few lines of code to re-launch the same exe with a few extra arguments to invoke the debugger and output an xml file to std::out.

    string tempFile = Path.GetTempFileName();
    Mutex handle = new Mutex(true, typeof(Program).Namespace + "-self-debugging");
    try
    {
        Process pDebug = Process.Start(typeof(Program).Assembly.Location,
            "debug-dump " + Process.GetCurrentProcess().Id + " " + tempFile);
        if (pDebug != null)
            pDebug.WaitForExit();
    }
    catch { }
    finally
    {
        handle.ReleaseMutex();
    }
    
    Console.WriteLine(File.ReadAllText(tempFile));
    

    Step 3 - Write the debug dump routine, this can be in the same exe or in a different exe. You will need to reference (or include the source from) the 'raw', 'corapi', and 'mdbgeng' modules from the sample. Then add a few lines to your Main():

    public static void Main(string[] args)
    {
        if (args.Length > 0 && args[0] == "debug-dump")
        {   //debug-dump process by id = args[1], output = args[2]
            using (XmlTextWriter wtr = new XmlTextWriter(args[2], Encoding.ASCII))
            {
                wtr.Formatting = Formatting.Indented;
                PerformDebugDump(Int32.Parse(args[1]), wtr);
            }
            return;
        }
        //... continue normal program execution
    }
    
    static void PerformDebugDump(int process, XmlWriter x)
    {
        x.WriteStartElement("process");
        x.WriteAttributeString("id", process.ToString());
        x.WriteAttributeString("time", XmlConvert.ToString(DateTime.Now, XmlDateTimeSerializationMode.RoundtripKind));
    
        MDbgEngine e = new MDbgEngine();
        MDbgProcess me = e.Attach(process);
        me.Go().WaitOne();
    
        try
        {
            x.WriteStartElement("modules");
            foreach (MDbgModule mod in me.Modules)
                x.WriteElementString("module", mod.CorModule.Name);
            x.WriteEndElement();
    
            foreach (MDbgThread thread in me.Threads)
            {
                x.WriteStartElement("thread");
                x.WriteAttributeString("id", thread.Id.ToString());
                x.WriteAttributeString("number", thread.Number.ToString());
                int ixstack = -1;
    
                foreach (MDbgFrame frame in thread.Frames)
                {
                    x.WriteStartElement("frame");
                    x.WriteAttributeString("ix", (++ixstack).ToString());
                    x.WriteAttributeString("loc", frame.ToString(String.Empty));
                    string valueText = null;
    
                    x.WriteStartElement("args");
                    try
                    {
                        foreach (MDbgValue value in frame.Function.GetArguments(frame))
                        {
                            x.WriteStartElement(value.Name);
                            x.WriteAttributeString("type", value.TypeName);
                            try { x.WriteAttributeString("value", value.GetStringValue(1, false)); }
                            finally { x.WriteEndElement(); }
                        }
                    }
                    catch { }
                    x.WriteEndElement();
    
                    x.WriteStartElement("locals");
                    try
                    {
                        foreach (MDbgValue value in frame.Function.GetActiveLocalVars(frame))
                        {
                            x.WriteStartElement(value.Name);
                            x.WriteAttributeString("type", value.TypeName);
                            try { x.WriteAttributeString("value", value.GetStringValue(1, false)); }
                            finally { x.WriteEndElement(); }
                        }
                    }
                    catch { }
                    x.WriteEndElement();
                    x.WriteEndElement();
                }
                x.WriteEndElement();
            }
        }
        finally
        {
            me.Detach().WaitOne();
        }
    
        x.WriteEndElement();
    }
    

    Example Output

    
    
    C:\Windows\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll
    ...etc
    
    
    
        
            
            
            
            
        
        
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
        
    
    
        
            
            
            
        
        
            
            
            
            
            
        
    
    ... etc
    
    
    

    Since you have the full power of a debugger there is nothing stopping you from writing as much or as little as you like, but the above example should get you started.

    UPDATE

    This works with the .Net 2.0 and/or 3.5 runtime without any further dependencies.

    This can debug .Net 2.0/3.5 code running in a .Net 4.0 process; however, it does not work with 4.0 (yet).

    For 4.0 CLR see this post: http://blogs.msdn.com/b/rmbyers/archive/2008/10/27/icordebug-re-architecture-in-clr-4-0.aspx

提交回复
热议问题