我正在尝试让我的应用程序(针对框架 .NET 4.0 编译的 VB.NET)编写自身的进程转储以帮助我进行调试。为此,我正在使用 Sysinternals 的 Procdump。
首先,我只需在单击事件上执行以下代码(因此调用堆栈上应该有可识别的内容):
Dim p As New Process
p.StartInfo.FileName = "C:\procdump.exe"
p.StartInfo.Arguments = "-accepteula -ma " & Process.GetCurrentProcess.Id
p.Start()
p.WaitForExit()
p.Dispose() ' Breakpoint
最后一行也是一个断点。
要创建转储,我在 VS 2010 中以调试模式启动应用程序,单击按钮以执行此代码,当它遇到断点时,我知道转储已被写入。此时,我还使用 Visual Studio 创建了另一个转储文件(Debug -> Save Dump As..)。
这给我留下了两个大小大致相等(400 Mb)的转储文件,一个由 Procdump.exe 创建,一个由 Visual Studio 创建。在不触及任何已构建的代码的情况下,我现在打开两个转储文件(在构建代码打开的情况下,我按 Ctrl+O)并在符号文件夹选项中指定调试输出文件夹。
现在,当我在 Visual Studio 创建的转储上单击“混合调试”时,我得到一个调用堆栈(在主线程上),其中包含可识别的方法名称,并且调试器将它很好地定位在源代码中的断点位置曾是。
但是,当我在 Procdump 创建的转储上单击“混合调试”时,(主线程的)调用堆栈仅包含诸如 clr.dll!6cb34e46()、KERNELBASE.dll!75106a8e() 和 ntdll.dll 之类的东西! 76f07094() 在顶部。没有可识别的代码,也没有与手表相关的内容。
这是为什么? 实际上,我期望这两个转储几乎相等(仅通过几行代码)。 [与附加的调试器有关,请参阅下面的编辑。]
请注意,在这两种情况下都正确加载了符号。我在 Debug->Windows->Modules 中获得的列表显示了要为两个转储加载的相同符号。此外,如果我在两个转储中切换到后台线程,我会在两个转储中为这些(及其变量的值等)获得正确的调用堆栈。
编辑
我注意到,通过在没有附加调试器的情况下执行应用程序,我得到了预期的进程转储(即,等于 Visual Studio 捕获的进程转储,但相差一行)。问题解决了。但是我仍然很好奇为什么在附加调试器的情况下我没有得到这个结果。