如何使用 C# 从 C++ 应用程序获取调用堆栈?
Posted
技术标签:
【中文标题】如何使用 C# 从 C++ 应用程序获取调用堆栈?【英文标题】:How can I get callstack from C++ application using C#? 【发布时间】:2014-03-11 10:51:33 【问题描述】:我有 C#/VB.NET 应用程序,用于测试用 C++ 编写的其他应用程序。如果 C++ 应用程序没有响应,我想从中获取调用堆栈。我发现了各种用 C++ 编写的示例(例如 dbghelp.dll CaptureStackBackTrace 或 Walking the callstack),但我在编写的 C# 中一无所获。你能帮帮我吗?
【问题讨论】:
【参考方案1】:我能想到几个选项,但没有一个使用 c#。
-
使用 adplus 或 procdump 创建进程的转储。
使用任务管理器并右键单击创建进程转储。注意进程是32位还是64位,需要用同位任务管理器进行转储。
然后使用 windbg 或 Visual Studio 查看转储。
您可以通过使用命令行参数调用其中任何一个来自动让 adplus 或 procdump 在 c# 中获取转储。这仍然无法为您提供调用堆栈,但如果您遇到涉及多个线程的死锁,您可能需要查看多个调用堆栈。
您也可以查看此链接 - 但它建议您需要编写一个调试器或找到一些可以执行此操作的库。
http://social.msdn.microsoft.com/Forums/en-US/90770a1c-7f83-4f81-864f-e64f3e17d02b/get-or-dispaly-call-stack-of-another-process-or-exe-file-in-my-apllication-in-c?forum=netfxbcl
另一个选择是使用 C++ 中的“Walking the callstack”示例。您可以制作一个可执行文件,该可执行文件将进程 id 和可能的文件名作为命令行参数(可以使用 guid),然后等待该文件被写入(不好玩 - 但可行)。或者您可以尝试使用托管 c++ 并将调用包装到非托管的东西(可能更不有趣,但可能更“正确”)。
【讨论】:
谢谢。但就像你说的......转储文件离调用堆栈还很远。即使使用我的 VS2012,我也无法从正在运行的进程转储中获取调用堆栈。我更喜欢文本形式的东西。 我添加了更多选项,但无论您最终做什么,都会有一些工作。【参考方案2】:这是我的团队成员的 VB.NET 实现:
-
下载ADPlus并将其添加到项目中。 ADPlus 包含在Debugging Tools for Windows 中。
使用以下代码调用它:
Public Shared Sub DumpCallStack(processID As Integer, outputFolder As String)
Const serverSymbolPath As String = "http://msdl.microsoft.com/download/symbols"
Const localSymbolFolder As String = "c:\temp\localSymbols"
Dim symbolFolderPath As String = String.Format("SRV*0* 1", serverSymbolPath, localSymbolFolder)
Directory.CreateDirectory(localSymbolFolder)
Directory.CreateDirectory(outputFolder)
Dim arguments As String = String.Format("/c Cscript //nologo ""0"" -quiet -quick -NoTlist -p 1 -dbg ""2"" -yp ""3"" -o ""4""",
"c:\Adplus\x64\adplus.vbs",
processID,
"CDB.exe",
symbolFolderPath,
outputFolder)
Dim pro As Process = New Process()
pro.StartInfo.FileName = "cmd.exe"
pro.StartInfo.Arguments = arguments
pro.StartInfo.UseShellExecute = False
pro.StartInfo.EnvironmentVariables("_NT_SYMBOL_PATH") = symbolFolderPath
pro.Start()
'wait up to 1 minute for the cmd.exe to exit
pro.WaitForExit(60000)
'Wait up to 1 minute for the windgb.exe to exit
WaitForProcessExit("cdb", 60000)
End Sub
Private Shared Sub WaitForProcessExit(processName As String, milliseconds As Integer)
Dim pros As Process() = Process.GetProcessesByName(processName)
If pros Is Nothing Then Return
For Each pro As Process In pros
pro.WaitForExit(milliseconds)
Next
End Sub
此调用会创建包含少量文件的目录。其中之一包含来自目标应用程序的调用堆栈。
【讨论】:
以上是关于如何使用 C# 从 C++ 应用程序获取调用堆栈?的主要内容,如果未能解决你的问题,请参考以下文章
如何从 C++ 后台任务(Windows 通用应用程序)调用 C# 函数?
如何从 C++ 代码引发事件并在另一个进程的 C# 代码中调用处理程序?