如何在VB.net中运行应用程序时打印行号

如何在VB.net中运行应用程序时打印行号,.net,vb.net,debugging,stack-trace,line-numbers,.net,Vb.net,Debugging,Stack Trace,Line Numbers,我想在VB.net应用程序中打印带有行号的调试消息。 我确实喜欢这个 Dim st As StackTrace Dim sf As StackFramee st = New StackTrace(New StackFrame(True)) sf = st.GetFrame(0) Console.WriteLine.("Line " & sf.GetFileLineNumber()) 我想把这个片段放到一个类中,每次我调用logMsg方法,用源代码中的行号记录我的消息。 但是我发现如果我

我想在VB.net应用程序中打印带有行号的调试消息。 我确实喜欢这个

Dim st As StackTrace
Dim sf As StackFramee
st = New StackTrace(New StackFrame(True))
sf = st.GetFrame(0)
Console.WriteLine.("Line " & sf.GetFileLineNumber())
我想把这个片段放到一个类中,每次我调用logMsg方法,用源代码中的行号记录我的消息。 但是我发现如果我把上面的代码片段放到一个类中,行号总是一样的,这就是我新的“st”行

<>函数与C++中的宏行函数完全相同。其实我是C++程序员。
如何解决这个问题?谢谢。

编译后的程序集将没有与之关联的行号。这不是属于程序集的信息

该信息保存在调试符号文件(pdb文件)中

从MSDN-:

StackTrace信息在调试构建配置中的信息量最大。默认情况下,调试生成包含调试符号,而发布生成不包含调试符号。调试符号包含用于构造StackFrame和StackTrace对象的大部分文件、方法名、行号和列信息


已编译的程序集将没有与其关联的行号。这不是属于程序集的信息

该信息保存在调试符号文件(pdb文件)中

从MSDN-:

StackTrace信息在调试构建配置中的信息量最大。默认情况下,调试生成包含调试符号,而发布生成不包含调试符号。调试符号包含用于构造StackFrame和StackTrace对象的大部分文件、方法名、行号和列信息


您显示的代码完全按照预期工作。它正在打印捕获堆栈帧的行号。因为您在另一个类中定义了它,所以它将打印包含该类的文件的行号

GetFrame方法在这里很重要。堆栈帧从0开始编号,0是最后一个推送的堆栈帧。因此,通过引用帧0,您指示运行时打印最后一个推送堆栈帧的行号。当一个方法调用另一个方法时,将创建一个新的堆栈帧

相反,你需要在几个重要方面改变你的方法。首先,需要获取推送到堆栈上的第一帧。其次,您可能希望接受一个参数,该参数包含有关您正在响应的异常的信息。尝试重写调试方法,使其看起来像这样:

Public Sub PrintCurrentLine(ByVal ex As Exception)
    Dim st As StackTrace = New StackTrace(ex)
    Dim sf As StackFrame = st.GetFrame(st.FrameCount - 1)
    Console.WriteLine("Line " & sf.GetFileLineNumber())
End Sub

还要记住,如果您在运行代码时启用了优化,那么行号之类的内容可能已经更改。您始终需要在代码中包含PDB文件,该文件包含在此类情况下使用的调试信息。它将优化后的代码映射回原始源代码。

您显示的代码完全按照预期工作。它正在打印捕获堆栈帧的行号。因为您在另一个类中定义了它,所以它将打印包含该类的文件的行号

GetFrame方法在这里很重要。堆栈帧从0开始编号,0是最后一个推送的堆栈帧。因此,通过引用帧0,您指示运行时打印最后一个推送堆栈帧的行号。当一个方法调用另一个方法时,将创建一个新的堆栈帧

相反,你需要在几个重要方面改变你的方法。首先,需要获取推送到堆栈上的第一帧。其次,您可能希望接受一个参数,该参数包含有关您正在响应的异常的信息。尝试重写调试方法,使其看起来像这样:

Public Sub PrintCurrentLine(ByVal ex As Exception)
    Dim st As StackTrace = New StackTrace(ex)
    Dim sf As StackFrame = st.GetFrame(st.FrameCount - 1)
    Console.WriteLine("Line " & sf.GetFileLineNumber())
End Sub

还要记住,如果您在运行代码时启用了优化,那么行号之类的内容可能已经更改。您始终需要在代码中包含PDB文件,该文件包含在此类情况下使用的调试信息。它将优化的代码映射回原始源。

在阅读了几个答案之后,我来了下面的解决方案,相当于C++宏线

。 例如,可将其用作:

Console.WriteLine(String.Format("Executed on line# {0}", (New StackTrace(New StackFrame(True))).GetFrame(0).GetFileLineNumber()))

在阅读了几个答案之后,我来了下面的解决方案,相当于C++宏线

例如,可将其用作:

Console.WriteLine(String.Format("Executed on line# {0}", (New StackTrace(New StackFrame(True))).GetFrame(0).GetFileLineNumber()))

非常感谢。对于我的例子,我有一个类来维护写入文件的日志消息。这就是为什么我必须在类中插入行号信息。所以这不是在不同的班级记录行号的方法,对吗?@heefan:嗯,是的。您可以遍历整个堆栈,寻找所需的单个帧。正如我前面提到的,GetFrame方法是关键,因为它允许您这样做。一旦确定了正确的帧,GetFileLineNumber将完全执行您想要的操作,当然,在没有可用调试信息的发布模式下除外。诀窍就在于抓住那个畜栏
ct堆栈帧,因为您正在调用另一个方法来处理调试。需要记住的重要一点是,每个方法调用都会创建一个新的堆栈框架。是的,你说得对。关键问题是应用程序计算帧时,即GetFrame。谢谢你的指导。我真的不知道这和C++有什么不同。如果使用_LINE宏,您不会遇到同样的问题吗?如果您在不同的源文件中调用一个方法,它将有不同的行号。为了获得正确的行号,必须在堆栈中找到正确的帧。不管怎样,不客气。@谢谢科迪。在C++中,它比VB.net更有用,也更容易。特别是在嵌入式Linux环境下,通过使用line文件和FUNC,我们可以快速获取调试消息行号并找到它们。我正在我的另一个项目中使用该系统。顺便说一句,有一个名为log4cpp的开源日志系统。无论如何,非常感谢。对于我的例子,我有一个类来维护写入文件的日志消息。这就是为什么我必须在类中插入行号信息。所以这不是在不同的班级记录行号的方法,对吗?@heefan:嗯,是的。您可以遍历整个堆栈,寻找所需的单个帧。正如我前面提到的,GetFrame方法是关键,因为它允许您这样做。一旦确定了正确的帧,GetFileLineNumber将完全执行您想要的操作,当然,在没有可用调试信息的发布模式下除外。诀窍是获得正确的堆栈帧,因为您正在调用另一个方法来处理调试。需要记住的重要一点是,每个方法调用都会创建一个新的堆栈框架。是的,你说得对。关键问题是应用程序计算帧时,即GetFrame。谢谢你的指导。我真的不知道这和C++有什么不同。如果使用_LINE宏,您不会遇到同样的问题吗?如果您在不同的源文件中调用一个方法,它将有不同的行号。为了获得正确的行号,必须在堆栈中找到正确的帧。不管怎样,不客气。@谢谢科迪。在C++中,它比VB.net更有用,也更容易。特别是在嵌入式Linux环境下,通过使用line文件和FUNC,我们可以快速获取调试消息行号并找到它们。我正在我的另一个项目中使用该系统。顺便说一句,有一个名为log4cpp的开源日志系统。无论如何,非常感谢。