Wie kann ich die Zeilennummer erhalten, die die Ausnahme ausgelöst hat?


198

catchWie kann ich in einem Block die Zeilennummer ermitteln, die eine Ausnahme ausgelöst hat?


Zur Laufzeit gibt es keinen Quellcode. Wofür wird diese Zeilennummer verwendet? Zum Zeitpunkt des Debuggens zeigt die IDE deutlich die Zeile an, die eine Ausnahme auslöst.
Ankitjaininfo



@ankitjaininfo nicht hilfreich, wenn es keine IDE gibt!
Michael

Beantwortet das deine Frage? Zeilennummer in Ausnahmebehandlung anzeigen
Liam

Antworten:


280

Wenn Sie die Zeilennummer nicht nur für den formatierten Stack-Trace benötigen, den Sie von Exception.StackTrace erhalten, können Sie die StackTrace- Klasse verwenden:

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();
}

Beachten Sie, dass dies nur funktioniert, wenn für die Assembly eine PDF-Datei verfügbar ist.


2
? (New StackTrace (ex, True)). GetFrame (0) .GetFileLineNumber () für eine einzelne VB-Zeile aus dem unmittelbaren Fenster.
Jonathan

34
C # one Liner:int line = (new StackTrace(ex, true)).GetFrame(0).GetFileLineNumber();
Gunwin

17
Dies gibt für mich immer 0 zurück. Wird dies dadurch verursacht, dass keine PDF-Datei vorhanden ist? Was ist das und wie bekommt man es? (Ich benutze ASP.net)
Brabbeldas

17
Warum verwenden Sie GetFrame (0)? Ich würde denken, dass Sie GetFrame (FrameCount-1) verwenden sollten.
Dewald Swanepoel

9
Ich habe den Vorschlag von @DewaldSwanepoel gefunden GetFrame(st.FrameCount-1), weitaus zuverlässiger zu sein.
Brad Martin

75

Verwenden Sie auf einfache Weise die Exception.ToString()Funktion, um die Zeile nach der Ausnahmebeschreibung zurückzugeben.

Sie können auch die Programm-Debug-Datenbank überprüfen, da sie Debug-Informationen / Protokolle über die gesamte Anwendung enthält.


Nun, MSDN denkt anders, dass es "eine Zeichenfolgendarstellung der aktuellen Ausnahme erstellt und zurückgibt": msdn.microsoft.com/en-us/library/…
Prokurors

Sie erhalten etwas Ähnliches wie:System.Exception: Test at Tests.Controllers.HomeController.About() in c:\Users\MatthewB\Documents\Visual Studio 2013\Projects\Tests\Tests\Controllers\HomeController.cs:line 22
Professor für Programmierung

3
Dies sollte die akzeptierte Antwort sein. Ich habe mich immer für ex.message entschieden und mich gefragt, warum dummes VB.net nicht in der Lage ist, die gleichen Informationen wie in Java zu erhalten.
Matthis Kohli

3
Es ist verrückt, dass diese Antwort nicht mehr positive Stimmen hat. Dies ist einfach, funktioniert zuverlässig und ist nicht mit den PDB-Einschränkungen verbunden.
Nick Painter

9
Exception.Messageist tot für mich. Nie wieder.
Stellen Sie Monica Cellio am

27

Wenn Sie die .PBODatei nicht haben :

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

Oder als Erweiterung der Exception-Klasse

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
Funktioniert leider nicht in einem nicht englischen Betriebssystem ("Zeilen" -Wort hängt vom Gebietsschema ab).
Ivan Kochurkin

2
@KvanTTT Sie können Regex.Matchmit :[^ ]+ (\d+)für den gleichen Effekt verwenden.
Dan Bechard

Diese Antwort funktioniert bei mir nicht, da ex.StackTrace nein hat :line und ich die PDB-Datei nicht habe.
Kriegsähnlicher Schimpanse

18

Sie können .PDBder Assembly zugeordnete Symboldateien einschließen , die Metadateninformationen enthalten. Wenn eine Ausnahme ausgelöst wird, enthält sie vollständige Informationen in der Stapelverfolgung, aus der diese Ausnahme stammt. Es enthält die Zeilennummern jeder Methode im Stapel.


Wie würde man vorgehen, um einen PDB aufzunehmen? Gibt es eine Möglichkeit, den PDB in der Anwendung zu bündeln / beim GAC zu registrieren?
Jacob Persi


6

Überprüfen Sie dieses

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

Update auf die Antwort

    // 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

Ich habe versucht, die Lösung By @ davy-c zu verwenden, hatte aber die Ausnahme "System.FormatException: 'Eingabezeichenfolge hatte nicht das richtige Format.'". Dies lag daran, dass nach der Zeilennummer immer noch Text vorhanden war. Ich habe den Code geändert gepostet und kam mit:

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 ", ""));

Dies funktioniert bei mir in VS2017 C #.


0

Erweiterungsmethode

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;
    }
}

Verwendung

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

Arbeiten für mich:

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

Ich habe der Ausnahme eine Erweiterung hinzugefügt, die die Zeile, Spalte, Methode, den Dateinamen und die Nachricht zurückgibt:

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

In der Datei Global.resx gibt es ein Ereignis namens Application_Error

Es wird ausgelöst, wenn ein Fehler auftritt. Sie können problemlos Informationen zu dem Fehler abrufen und diese an eine E-Mail zur Fehlerverfolgung senden.

Ich denke auch, alles was Sie tun müssen, ist die Datei global.resx zu kompilieren und ihre DLLs (2 DLLs) zu Ihrem Bin-Ordner hinzuzufügen, und es wird funktionieren!

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.