Come posso ottenere il numero di riga che ha generato l'eccezione?


198

In un catchblocco, come posso ottenere il numero di riga che ha generato un'eccezione?


in fase di esecuzione non esiste un codice sorgente. a cosa servirà questa linea no? al momento del debug, l'IDE mostra chiaramente la linea che genera un'eccezione.
ankitjaininfo il

possibile duplicato della gestione
Fredrik Mörk, il


@ankitjaininfo non è utile se non esiste un IDE!
Michael,

Risposte:


281

Se è necessario il numero di riga per oltre la traccia dello stack formattata ottenuta da Exception.StackTrace, è possibile utilizzare la classe 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();
}

Si noti che funzionerà solo se è disponibile un file pdb per l'assembly.


2
? (New StackTrace (ex, True)). GetFrame (0) .GetFileLineNumber () per VB a riga singola dalla finestra immediata.
Jonathan,

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

17
Questo restituisce sempre 0 per me. Questo è causato dal fatto di non avere un file pdb? Cos'è e come ottenerlo? (Sto usando ASP.net)
Brabbeldas,

17
Perché stai usando GetFrame (0)? Penserei che dovresti usare GetFrame (FrameCount-1).
Dewald Swanepoel,

9
Ho trovato il suggerimento di @DewaldSwanepoel di utilizzare GetFrame(st.FrameCount-1)per essere molto più affidabile.
Brad Martin,

75

Modo semplice, utilizzare la Exception.ToString()funzione, restituirà la riga dopo la descrizione dell'eccezione.

È inoltre possibile controllare il database di debug del programma in quanto contiene informazioni / registri di debug sull'intera applicazione.


Bene, MSDN la pensa diversamente: "Crea e restituisce una rappresentazione in formato stringa dell'eccezione corrente": msdn.microsoft.com/en-us/library/…
Prokurors

Ottieni qualcosa di simile a:System.Exception: Test at Tests.Controllers.HomeController.About() in c:\Users\MatthewB\Documents\Visual Studio 2013\Projects\Tests\Tests\Controllers\HomeController.cs:line 22
Professore di programmazione il

3
Questa dovrebbe essere la risposta accettata. Sono sempre andato per un messaggio e mi chiedevo perché lo stupido VB.net non fosse in grado di ottenere le stesse informazioni di Java.
Matthis Kohli,

3
È folle che questa risposta non abbia più voti. Questo è semplice, funziona in modo affidabile e non viene fornito con le avvertenze sul PDB.
Nick Painter,

9
Exception.Messageè morto per me. Mai più.
Ripristina Monica Cellio il

27

Se non hai il .PBOfile:

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

O come estensioni sulla classe 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
Sfortunatamente non funzionerà in un sistema operativo non inglese (la parola "linea" dipende dalle impostazioni locali).
Ivan Kochurkin,

2
@KvanTTT Puoi usarlo Regex.Matchcon :[^ ]+ (\d+)per lo stesso effetto.
Dan Bechard,

Questa risposta non funziona per me, poiché ex.StackTrace non ha :line e non ho il file PDB.
Warlike Chimpanzee,

18

È possibile includere .PDBfile di simboli associati all'assembly che contengono informazioni sui metadati e quando viene generata un'eccezione, conterrà informazioni complete nello stack di dove è stata originata questa eccezione. Conterrà i numeri di riga di ciascun metodo nello stack.


Come si potrebbe fare per includere un PDB? C'è un modo per raggruppare il PDB nell'applicazione / registrarlo nel GAC?
Jacob Persi,


6

Controlla questo

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

Aggiorna alla risposta

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

Ho provato a utilizzare la soluzione By @ davy-c ma avevo un'eccezione "System.FormatException: 'La stringa di input non era in un formato corretto.'", Ciò era dovuto al fatto che c'era ancora del testo oltre il numero di riga, ho modificato il codice pubblicato e inventato:

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

Questo funziona per me in VS2017 C #.


0

Metodo di estensione

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

uso

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

Lavorando per me:

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

Ho aggiunto un'estensione a Exception che restituisce la riga, la colonna, il metodo, il nome file e il messaggio:

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

Nel file Global.resx c'è un evento chiamato Application_Error

si attiva ogni volta che si verifica un errore, puoi facilmente ottenere qualsiasi informazione sull'errore e inviarlo a un'e-mail di tracciamento dei bug.

Inoltre penso che tutto ciò che devi fare è compilare global.resx e aggiungere le sue dll (2 dll) alla tua cartella bin e funzionerà!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.