如何获得引发异常的行号?


198

在一个catch块中,如何获取引发异常的行号?


在运行时没有源代码。此行号将用于什么?在调试时,IDE清楚地显示抛出异常的行。
ankitjaininfo



如果没有IDE,则@ankitjaininfo 没有帮助!
迈克尔

这回答了你的问题了吗?在例外处理中显示行号
Liam

Answers:


280

如果您需要行号不仅仅是从Exception.StackTrace获得的格式化堆栈跟踪,那么可以使用StackTrace类:

try
{
    throw new Exception();
}
catch (Exception ex)
{
    // Get stack trace for the exception with source file information
    var st = new StackTrace(ex, true);
    // Get the top stack frame
    var frame = st.GetFrame(0);
    // Get the line number from the stack frame
    var line = frame.GetFileLineNumber();
}

请注意,这仅在程序集有可用的pdb文件时才有效。


2
?(New StackTrace(ex,True))。GetFrame(0).GetFileLineNumber()从即时窗口中获取VB单行。
乔纳森(Jonathan)2012年

34
C#一线客:int line = (new StackTrace(ex, true)).GetFrame(0).GetFileLineNumber();
gunwin,

17
这总是为我返回0。这是由于没有pdb文件引起的吗?这是什么以及如何获得?(我正在使用ASP.net)
Brabbeldas

17
为什么使用GetFrame(0)?我认为您应该使用GetFrame(FrameCount-1)。
Dewald Swanepoel 2015年

9
我发现使用@DewaldSwanepoel的建议GetFrame(st.FrameCount-1)要可靠得多。
布莱德·马丁

75

使用Exception.ToString()函数的简单方法,它将在异常描述之后返回该行。

您还可以检查程序调试数据库,因为它包含有关整个应用程序的调试信息/日志。


那么MSDN认为不同,它“创建并返回当前异常的字符串表示”:msdn.microsoft.com/en-us/library/...
Prokurors

您得到的类似于:System.Exception: Test at Tests.Controllers.HomeController.About() in c:\Users\MatthewB\Documents\Visual Studio 2013\Projects\Tests\Tests\Controllers\HomeController.cs:line 22
编程教授,

3
这应该是公认的答案。我总是去找ex.message,想知道为什么愚蠢的VB.net无法获得与Java中相同的信息。
Matthis Kohli

3
疯狂的是,这个答案没有更多的投票。这很简单,工作可靠,并且没有PDB警告。
Nick Painter

9
Exception.Message对我死了 再也不。
恢复莫妮卡·塞利奥(Monica Cellio)'18

27

如果没有该.PBO文件:

C#

public int GetLineNumber(Exception ex)
{
    var lineNumber = 0;
    const string lineSearch = ":line ";
    var index = ex.StackTrace.LastIndexOf(lineSearch);
    if (index != -1)
    {
        var lineNumberText = ex.StackTrace.Substring(index + lineSearch.Length);
        if (int.TryParse(lineNumberText, out lineNumber))
        {
        }
    }
    return lineNumber;
}

Vb.net

Public Function GetLineNumber(ByVal ex As Exception)
    Dim lineNumber As Int32 = 0
    Const lineSearch As String = ":line "
    Dim index = ex.StackTrace.LastIndexOf(lineSearch)
    If index <> -1 Then
        Dim lineNumberText = ex.StackTrace.Substring(index + lineSearch.Length)
        If Int32.TryParse(lineNumberText, lineNumber) Then
        End If
    End If
    Return lineNumber
End Function

或作为Exception类的扩展

public static class MyExtensions
{
    public static int LineNumber(this Exception ex)
    {
        var lineNumber = 0;
        const string lineSearch = ":line ";
        var index = ex.StackTrace.LastIndexOf(lineSearch);
        if (index != -1)
        {
            var lineNumberText = ex.StackTrace.Substring(index + lineSearch.Length);
            if (int.TryParse(lineNumberText, out lineNumber))
            {
            }
        }
        return lineNumber;
    }
}   

8
不幸的是,不能在非英语操作系统中工作(“行”字取决于地区)。
伊万·科胡金

2
@KvanTTT您可以使用Regex.Matchwith :[^ ]+ (\d+)获得相同的效果。
丹·贝查德

这个答案对我不起作用,因为ex.StackTrace没有,:line 而且我没有PDB文件。
好战的黑猩猩

18

您可以包括.PDB与程序集关联的符号文件,其中包含元数据信息,并且在引发异常时,它将在堆栈跟踪中包含此异常起源的完整信息。它将包含堆栈中每个方法的行号。


如何包括一个PDB?有没有办法将PDB捆绑到应用程序中/将其注册到GAC?
Jacob Persi


6

检查这个

StackTrace st = new StackTrace(ex, true);
//Get the first stack frame
StackFrame frame = st.GetFrame(0);

//Get the file name
string fileName = frame.GetFileName();

//Get the method name
string methodName = frame.GetMethod().Name;

//Get the line number from the stack frame
int line = frame.GetFileLineNumber();

//Get the column number
int col = frame.GetFileColumnNumber();

1

更新答案

    // Get stack trace for the exception with source file information
    var st = new StackTrace(ex, true);
    // Get the top stack frame
    var frame = st.GetFrame(st.FrameCount-1);
    // Get the line number from the stack frame
    var line = frame.GetFileLineNumber();

1

我尝试使用@ davy-c解决方案,但出现异常“ System.FormatException:'输入字符串的格式不正确。'”,这是由于行号之后仍然有文本,我修改了代码发布并提出:

int line = Convert.ToInt32(objErr.ToString().Substring(objErr.ToString().IndexOf("line")).Substring(0, objErr.ToString().Substring(objErr.ToString().IndexOf("line")).ToString().IndexOf("\r\n")).Replace("line ", ""));

这在VS2017 C#中对我有用。


0

扩展方式

static class ExceptionHelpers
{
    public static int LineNumber(this Exception ex)
    {
        int n;
        int i = ex.StackTrace.LastIndexOf(" ");
        if (i > -1)
        {
            string s = ex.StackTrace.Substring(i + 1);
            if (int.TryParse(s, out n))
                return n;
        }
        return -1;
    }
}

用法

try
{
    throw new Exception("A new error happened");
}
catch (Exception ex)
{
    //If error in exception LineNumber() will be -1
    System.Diagnostics.Debug.WriteLine("[" + ex.LineNumber() + "] " + ex.Message);
}

0

为我工作:

var st = new StackTrace(e, true);

// Get the bottom stack frame
var frame = st.GetFrame(st.FrameCount - 1);
// Get the line number from the stack frame
var line = frame.GetFileLineNumber();
var method = frame.GetMethod().ReflectedType.FullName;
var path = frame.GetFileName();

0

我向Exception添加了扩展,该扩展返回行,列,方法,文件名和消息:

public static class Extensions
{
    public static string ExceptionInfo(this Exception exception)
    {

        StackFrame stackFrame = (new StackTrace(exception, true)).GetFrame(0);
        return string.Format("At line {0} column {1} in {2}: {3} {4}{3}{5}  ",
           stackFrame.GetFileLineNumber(), stackFrame.GetFileColumnNumber(),
           stackFrame.GetMethod(), Environment.NewLine, stackFrame.GetFileName(),
           exception.Message);

    }
}

-3

在Global.resx文件中,有一个名为Application_Error的事件。

它会在发生错误时触发,您可以轻松获取有关该错误的任何信息,并将其发送到错误跟踪电子邮件。

另外,我认为您需要做的就是编译global.resx并将其dll(2个dll)添加到bin文件夹中,它将起作用!

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.