Como posso obter o número da linha que gerou uma exceção?


198

Em um catchbloco, como posso obter o número da linha que lançou uma exceção?


em tempo de execução, não há código fonte. Para que essa linha não será usada? no momento da depuração, o IDE mostra claramente a linha que gera uma exceção.
Ankitjaininfo

possível duplicação do tratamento
Fredrik Mörk


@ankitjaininfo não é útil se não houver IDE!
Michael

Respostas:


280

Se você precisar do número da linha para mais do que apenas o rastreamento de pilha formatado obtido de Exception.StackTrace, poderá usar a 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();
}

Observe que isso só funcionará se houver um arquivo pdb disponível para o assembly.


2
? (Novo StackTrace (ex, True)). GetFrame (0) .GetFileLineNumber () para VB linha única a partir da janela imediata.
18712 Jonathan

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

17
Isso sempre retorna 0 para mim. Isso é causado por não ter um arquivo pdb? O que é e como obtê-lo? (Estou usando ASP.net)
Brabbeldas

17
Por que você está usando GetFrame (0)? Eu acho que você deveria estar usando GetFrame (FrameCount-1).
Dewald Swanepoel

9
Eu achei a sugestão do @DewaldSwanepoel de usar GetFrame(st.FrameCount-1)muito mais confiável.
Brad Martin

75

De maneira simples, use a Exception.ToString()função, ela retornará a linha após a descrição da exceção.

Você também pode verificar o banco de dados de depuração do programa, pois ele contém informações / logs de depuração sobre todo o aplicativo.


Bem MSDN pensa diferente, que "Cria e retorna uma representação de seqüência a exceção atual": msdn.microsoft.com/en-us/library/...
Prokurors

Você obtém algo semelhante 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
Professor de programação

3
Essa deve ser a resposta aceita. Eu sempre fui ao ex.message e me perguntei por que o estúpido VB.net não é capaz de obter as mesmas informações que em Java.
Matthis Kohli

3
É uma loucura que essa resposta não tenha mais votos positivos. Isso é simples, funciona de maneira confiável e não vem com as advertências do PDB.
Nick Painter

9
Exception.Messageestá morto para mim. Nunca mais.
Reintegrar Monica Cellio

27

Se você não possui o .PBOarquivo:

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

Ou como uma extensão na 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
Infelizmente, não funcionará no sistema operacional não inglês (a palavra "linha" depende da localidade).
Ivan Kochurkin

2
@KvanTTT Você pode usar Regex.Matchcom :[^ ]+ (\d+)o mesmo efeito.
precisa

Esta resposta não funciona para mim, pois o ex.StackTrace não tem :line e eu não tenho o arquivo PDB.
Chimpanzé guerreiro

18

Você pode incluir .PDBarquivos de símbolos associados à montagem que contêm informações de metadados e, quando uma exceção é lançada, ela contém informações completas no rastreamento de pilha de onde essa exceção se originou. Ele conterá os números de linha de cada método na pilha.


Como se poderia incluir um PDB? Existe uma maneira de agrupar o PDB no aplicativo / registrá-lo no GAC?
Jacob Persi


6

Confira este

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

Atualize para a resposta

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

Tentei usar a solução By @ davy-c, mas tinha uma exceção "System.FormatException: 'String de entrada não estava no formato correto.'", Isso ocorreu porque ainda havia texto após o número da linha, modifiquei o código postou e veio com:

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

Isso funciona para mim no VS2017 C #.


0

Método de Extensão

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

Trabalhando para mim:

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

Eu adicionei uma extensão ao Exception que retorna a linha, coluna, método, nome do arquivo e mensagem:

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

No arquivo Global.resx, há um evento chamado Application_Error

ele é acionado sempre que ocorre um erro, você pode facilmente obter qualquer informação sobre o erro e enviá-lo para um e-mail de rastreamento de bug.

Também acho que tudo o que você precisa fazer é compilar o global.resx e adicionar suas DLLs (2 DLLs) à sua pasta bin e ele funcionará!

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.