在我的应用程序中生成/创建mdump文件

我正在寻找一种方法来生成我的应用程序中的minidump文件, 类似于ProcDump所做的,但是使用代码并且不必提取3dparty工具。

不想使用ProcDump的主要原因是:
1)二进制文件的大小会大大增加(这是一个问题,因为我的应用程序是免费软件,带宽不是免费的)。
2)感觉很脏。
3)我无法移植该应用程序来运行Windows Mobile。

我的要求是:
1)能够在fatale崩溃中生成mdump文件。
2)能够“暂停”应用程序执行转储,并且contiune将是一个奖励

如果这不是一个真正的选项,有没有办法动态地获取当前上下文中的局部变量值?

旁注:我确实读过这篇文章,但它已经很老了所以我非常犹豫不决我的工作。
似乎IE 9或网站存在问题,因此我遇到了标签问题。

因此,有一种解决方案可以想到并满足以下目标:

  • 二进制文件的大小将增加大约300k
  • 能够在fatale崩溃中生成mdump文件。
  • 能够“暂停”应用程序执行转储,并且contiune将是一个奖励

我会给这个要求一个完整的未知数:

  • 我无法移植该应用程序来运行Windows Mobile。

那么解决方案是什么?

从Microsoft Sample for MDbg.exe集成所需的所需部件,为您提供一个“即时”调试器,用于附加,转储和分离崩溃过程。

步骤1 – 首先从这里将源代码下载到mdbg: http : //www.microsoft.com/downloads/en/details.aspx? FamilyID = 38449a42-6b7a-ee4-80ce-c55645ab1310&DisplayLang = en

第2步 – 创建一个“崩溃”处理程序,它生成一个调试器进程并等待完成。 我使用以下几行代码重新启动相同的exe,并使用一些额外的参数来调用调试器并将xml文件输出到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)); 

步骤3 – 编写调试转储例程,这可以在同一个exe或不同的exe中。 您需要从示例中引用(或包括来自)’raw’,’corapi’和’mdbgeng’模块。 然后在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(); } 

示例输出

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

因为你拥有调试器的全部function,所以没有什么可以阻止你编写你想要的那么多或者尽可能多的东西,但上面的例子应该让你开始。

UPDATE

这适用于.Net 2.0和/或3.5运行时,没有任何进一步的依赖性。

这可以调试在.Net 4.0进程中运行的.Net 2.0 / 3.5代码; 但是,它不适用于4.0(尚未)。

对于4.0 CLR,请参阅此post: http : //blogs.msdn.com/b/rmbyers/archive/2008/10/27/icordebug-re-architecture-in-clr-4-0.aspx

您可以从AppDomain.UnhandledException或Application.ThreadException事件处理程序调用MiniDumpWriteDump来创建minidump。 本文详细介绍了该function: 有效的小型转储

您也可以使用具有其他function的库: 使用BugTrap捕获所有错误!

编辑

看起来像获得一个有用的minidump并不是那么容易。 首先,当转储未满时,sos.dll会抱怨(完全转储大约为100-150MB)。 其次,不建议在catch块中写入dump: 抛出exception时获取良好的转储。

如果你有一个winforms应用程序,这个问题有一些有用的信息: SetUnhandledExceptionFilter如何在.NET WinForms应用程序中工作?