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?

MBZ
quelle
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
1
Mögliches Duplikat von Zeilennummer in Ausnahmebehandlung anzeigen
Thom Smith
@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.

Quartiermeister
quelle
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.

SimpleButPerfect
quelle
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;
    }
}   
Radbyx
quelle
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.

Darin Dimitrov
quelle
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
7

Es klappt:

var LineNumber = new StackTrace(ex, True).GetFrame(0).GetFileLineNumber();
Thirisangu Ramanathan
quelle
Was ist mit unbehandelten Ausnahmen? wie UnhandledExceptionEventArgsObjekt
Yousha Aleayoub
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();
Ram Maurya
quelle
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();
Sean Fleming
quelle
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 #.

Joseph Michael
quelle
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);
}
Arvo Bowen
quelle
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();
Shivendra Singh
quelle
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);

    }
}
vyengr
quelle
-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!

Khaled
quelle