在堆栈跟踪中获取 VB.NET 行号

Posted

技术标签:

【中文标题】在堆栈跟踪中获取 VB.NET 行号【英文标题】:Getting VB.NET line numbers in stack trace 【发布时间】:2012-12-12 10:31:35 【问题描述】:

我有一个 VB.NET 2010 Winforms 应用程序,我想在堆栈跟踪中包含行号。我已阅读以下问题和答案:

how to print out line number during application run in VB.net

其中提到“您始终需要在代码中包含 PDB 文件,其中包含在这种情况下使用的调试信息”。在高级编译器设置下,我尝试将“生成调试信息”作为“仅 pdb”和“完整”用于我的发布版本,并确认在与我的 EXE 相同的目录中生成了一个新的 PDB 文件。然而,以下测试代码为每个堆栈帧生成一个零行号,并且不返回文件名:

    Dim st As StackTrace = New StackTrace(ex)
    For Each sf As StackFrame In st.GetFrames
        MsgBox("Line " & sf.GetFileLineNumber() & sf.GetFileName)
    Next

但是,下面的代码直接生成了一个看起来不错的堆栈跟踪,因此通常异常处理程序似乎没有问题:

ExceptionDetails.Text = ex.GetType.ToString & "(0x" & hr.ToString("X8") & "): " & ex.Message & vbCrLf & ex.StackTrace

我似乎在项目配置下找不到任何其他可能的设置,并想知道是否有人对可能导致此问题的其他事情有想法。我在这里和其他地方搜索到的所有解决方案似乎只是建议确保 PDB 与可执行文件位于同一路径中。

【问题讨论】:

【参考方案1】:

来自您正在调用的构造函数的documentation:

StackTrace 是使用调用者的当前线程创建的,不包含文件名、行号或列信息。

尝试使用:

Dim st As StackTrace = New StackTrace(ex, True)

改为使用this constructor。第二个构造函数参数描述为:

true 捕获文件名、行号和列号;否则为假。

【讨论】:

【参考方案2】:

尝试使用

public StackTrace(Exception e, bool fNeedFileInfo);

构造函数并将 fNeedFileInfo 设置为 true

【讨论】:

【参考方案3】:

这个问题已经解决了一段时间,但我想我会分享我最近在我的项目中包含的最终工作功能。它返回初始异常信息和此时的完整堆栈跟踪,后跟堆栈跟踪中导致异常的行号和文件名。

Public Function GetExceptionInfo(ex As Exception) As String
    Dim Result As String
    Dim hr As Integer = Runtime.InteropServices.Marshal.GetHRForException(ex)
    Result = ex.GetType.ToString & "(0x" & hr.ToString("X8") & "): " & ex.Message & Environment.NewLine & ex.StackTrace & Environment.NewLine
    Dim st As StackTrace = New StackTrace(ex, True)
    For Each sf As StackFrame In st.GetFrames
        If sf.GetFileLineNumber() > 0 Then
            Result &= "Line:" & sf.GetFileLineNumber() & " Filename: " & IO.Path.GetFileName(sf.GetFileName) & Environment.NewLine
        End If
    Next
    Return Result
End Function

【讨论】:

这太棒了。感谢发帖:) 对我来说,这只有在 PDB 文件也被分发的情况下才有效。我错过了什么吗?如果未分发 PDB,则不会显示“行”或“文件名”信息。 @Oliver 没错,PDB 包含行号和文件名(我相信它们实际上不包含太多其他内容),因此您需要分发它们才能正常工作。 @PeterJ 确定我在这里遗漏了一些东西...如果 PDB 已分发,ex.ToString 将提供所有需要的信息,包括行号和文件,至少在我工作过的场景中。是否有行/文件不在异常信息中的情况? @Oliver 在我问我不知道的问题时ex.ToString 提供了所有信息,所以我想我走这条路是为了尝试获取行号,但除了给出Win32 异常代码有时很方便,并且允许一些自定义格式,此方法与使用它相比没有优势。无论哪种方式,您都需要 PDB 文件,因此如果您对 ex.ToString 的输出感到满意,您不妨坚持下去。

以上是关于在堆栈跟踪中获取 VB.NET 行号的主要内容,如果未能解决你的问题,请参考以下文章

csharp 获取具有错误文本,方法和行号的完整堆栈跟踪

Kotlin 代码堆栈跟踪显示 Java 行号

UWP 应用的堆栈跟踪中的行号

在发布模式下显示 .NET 程序集的堆栈跟踪中的行号

启用 ASP.NET 模拟时,异常堆栈跟踪中缺少行号

Proguard 不保留堆栈跟踪中的行号和方法名称