Jak mogę uzyskać numer linii, który zwrócił wyjątek?


198

W catchbloku, w jaki sposób mogę uzyskać numer linii, który zgłosił wyjątek?


w czasie wykonywania nie ma kodu źródłowego. do czego ta linia nie będzie używana? w czasie debugowania IDE wyraźnie pokazuje linię, która zgłasza wyjątek.
ankitjaininfo



@ankitjaininfo nie jest pomocne, jeśli nie ma IDE!
Michael

Czy to odpowiada na twoje pytanie? Pokaż numer linii w obsłudze wyjątków
Liam

Odpowiedzi:


281

Jeśli potrzebujesz numeru wiersza do więcej niż tylko sformatowanego śledzenia stosu uzyskanego z Exception.StackTrace, możesz użyć klasy 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();
}

Zauważ, że zadziała to tylko wtedy, gdy dla zestawu dostępny jest plik pdb.


2
? (Nowy StackTrace (np. True)). GetFrame (0) .GetFileLineNumber () dla pojedynczej linii VB z bezpośredniego okna.
Jonathan

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

17
To zawsze zwraca mi 0. Czy jest to spowodowane brakiem pliku pdb? Co to jest i jak go zdobyć? (Używam ASP.net)
Brabbeldas

17
Dlaczego korzystasz z GetFrame (0)? Myślę, że powinieneś używać GetFrame (FrameCount-1).
Dewald Swanepoel

9
Znalazłem sugestię @DewaldSwanepoel, GetFrame(st.FrameCount-1)aby była bardziej niezawodna.
Brad Martin

75

Prosto, użyj Exception.ToString()funkcji, zwróci wiersz po opisie wyjątku.

Możesz także sprawdzić bazę danych debugowania programu, ponieważ zawiera informacje / dzienniki debugowania dotyczące całej aplikacji.


Cóż, MSDN myśli inaczej, że „Tworzy i zwraca ciąg reprezentujący bieżący wyjątek”: msdn.microsoft.com/en-us/library/…
Prokurors

Otrzymasz coś podobnego do:System.Exception: Test at Tests.Controllers.HomeController.About() in c:\Users\MatthewB\Documents\Visual Studio 2013\Projects\Tests\Tests\Controllers\HomeController.cs:line 22
Profesora programowania

3
To powinna być zaakceptowana odpowiedź. Zawsze szukałem np. Wiadomości i zastanawiałem się, dlaczego głupie VB.net nie jest w stanie uzyskać takich samych informacji jak w Javie.
Matthis Kohli,

3
To szalone, że ta odpowiedź nie ma więcej pozytywnych opinii. Jest to proste, działa niezawodnie i nie jest objęte zastrzeżeniami PDB.
Nick Painter

9
Exception.Messagejest dla mnie martwy. Nigdy więcej.
Przywróć Monikę Cellio

27

Jeśli nie masz .PBOpliku:

DO#

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

Lub jako rozszerzenie klasy 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
Niestety nie będzie działać w systemie operacyjnym innym niż angielski (słowo „linia” zależy od ustawień regionalnych).
Ivan Kochurkin

2
@KvanTTT Możesz użyć Regex.Matchz :[^ ]+ (\d+)tym samym efektem.
Dan Bechard

Ta odpowiedź nie działa dla mnie, ponieważ ex.StackTrace nie ma :line i nie mam pliku PDB.
Warlike Chimpanzee

18

Możesz dołączyć .PDBpliki symboli powiązane ze złożeniem, które zawierają informacje o metadanych, a kiedy zgłoszony zostanie wyjątek, będzie on zawierał pełne informacje w ścieżce stosu, z której pochodzi ten wyjątek. Będzie zawierać numery linii każdej metody na stosie.


Jak można by włączyć PDB? Czy istnieje sposób na dołączenie PDB do aplikacji / zarejestrowanie go w GAC?
Jacob Persi


6

Sprawdź ten

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

Zaktualizuj odpowiedź

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

Próbowałem użyć rozwiązania By @ davy-c, ale miałem wyjątek „System.FormatException:„ Łańcuch wejściowy nie był w poprawnym formacie. ””, Było to spowodowane tym, że nadal był tekst po numerze linii, zmodyfikowałem kod on opublikował i wymyślił:

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

Działa to dla mnie w VS2017 C #.


0

Metoda przedłużenia

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

Stosowanie

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

Pracuje dla mnie:

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

Dodałem rozszerzenie do wyjątku, które zwraca wiersz, kolumnę, metodę, nazwę pliku i komunikat:

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

W pliku Global.resx znajduje się zdarzenie o nazwie Błąd_aplikacji

uruchamia się za każdym razem, gdy wystąpi błąd ,, możesz łatwo uzyskać wszelkie informacje o błędzie i wysłać je na e-mail śledzenia błędów.

Myślę też, że wszystko, co musisz zrobić, to skompilować plik global.resx i dodać jego biblioteki DLL (2 biblioteki DLL) do folderu bin i będzie działać!

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.