¿Cómo puedo obtener el número de línea que arrojó la excepción?

198

En un catchbloque, ¿cómo puedo obtener el número de línea que arrojó una excepción?

MBZ
fuente
en tiempo de ejecución no hay código fuente. ¿Para qué se utilizará esta línea? en el momento de la depuración, el IDE muestra claramente la línea que arroja una excepción.
ankitjaininfo
posible duplicado del manejo
Fredrik Mörk
1
posible duplicado de Mostrar número de línea en manejo de excepciones
Thom Smith
¡@ankitjaininfo no es útil si no hay IDE!
Michael
¿Responde esto a tu pregunta? Mostrar número de línea en manejo de excepciones
Liam

Respuestas:

280

Si necesita el número de línea para algo más que el seguimiento de pila formateado que obtiene de Exception.StackTrace, puede usar la clase 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();
}

Tenga en cuenta que esto solo funcionará si hay un archivo pdb disponible para el ensamblado.

Quartermeister
fuente
2
? (New StackTrace (ex, True)). GetFrame (0) .GetFileLineNumber () para una sola línea VB desde la ventana inmediata.
Jonathan
34
C # one liner:int line = (new StackTrace(ex, true)).GetFrame(0).GetFileLineNumber();
gunwin
17
Esto siempre devuelve 0 para mí. ¿Es esto causado por no tener un archivo pdb? ¿Qué es y cómo obtenerlo? (Estoy usando ASP.net)
Brabbeldas
17
¿Por qué estás usando GetFrame (0)? Creo que debería estar usando GetFrame (FrameCount-1).
Dewald Swanepoel
9
He encontrado que la sugerencia de @DewaldSwanepoel de usar GetFrame(st.FrameCount-1)es mucho más confiable.
Brad Martin
75

De manera simple, use la Exception.ToString()función, devolverá la línea después de la descripción de la excepción.

También puede consultar la base de datos de depuración del programa, ya que contiene información / registros de depuración sobre toda la aplicación.

SimpleButPerfect
fuente
Bueno, MSDN piensa de manera diferente, que "Crea y devuelve una representación de cadena de la excepción actual": msdn.microsoft.com/en-us/library/…
Prokurors
Obtienes algo similar 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
Profesor de programación el
3
Esta debería ser la respuesta aceptada. Siempre elegí ex.message y me pregunté por qué el estúpido VB.net no puede obtener la misma información que en Java.
Matthis Kohli
3
Es una locura que esta respuesta no tenga más votos a favor. Esto es simple, funciona de manera confiable y no viene con las advertencias de PDB.
Nick Painter
9
Exception.Messageestá muerto para mí Nunca más.
Vuelva a instalar Monica Cellio
27

Si no tienes el .PBOarchivo:

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 como extensiones en la clase Excepción

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
fuente
8
Lamentablemente no funcionará en un sistema operativo que no esté en inglés (la palabra "línea" depende del entorno local)
Ivan Kochurkin
2
@KvanTTT Se puede usar Regex.Matchcon :[^ ]+ (\d+)el mismo efecto.
Dan Bechard
Esta respuesta no me funciona, ya que, por ejemplo, StackTrace no tiene :line y no tengo el archivo PDB.
Chimpancé guerrero
18

Puede incluir .PDBarchivos de símbolos asociados al ensamblaje que contengan información de metadatos y cuando se lanza una excepción, contendrá información completa en el stacktrace de dónde se originó esta excepción. Contendrá números de línea de cada método en la pila.

Darin Dimitrov
fuente
¿Cómo se podría incluir un PDB? ¿Hay alguna manera de agrupar el PDB en la aplicación / registrarlo en el GAC?
Jacob Persi
7

Funciona:

var LineNumber = new StackTrace(ex, True).GetFrame(0).GetFileLineNumber();
Thirisangu Ramanathan
fuente
¿Qué pasa con las excepciones no manejadas? como UnhandledExceptionEventArgsobjeto
Yousha Aleayoub
6

Revisa 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();
Ram Maurya
fuente
1

Actualizar a la respuesta

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

Intenté usar la solución By @ davy-c pero tuve una excepción "System.FormatException: 'La cadena de entrada no estaba en un formato correcto'", esto se debía a que todavía había texto más allá del número de línea, modifiqué el código. publicado y se le ocurrió:

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

Esto funciona para mí en VS2017 C #.

Joseph Michael
fuente
0

Método de extensión

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);
}
Arvo Bowen
fuente
0

Trabajando para mi

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
fuente
0

Agregué una extensión a Exception que devuelve la línea, columna, método, nombre de archivo y mensaje:

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
fuente
-3

En el archivo Global.resx hay un evento llamado Application_Error

se activa cada vez que se produce un error, puede obtener fácilmente cualquier información sobre el error y enviarlo a un correo electrónico de seguimiento de errores.

¡También creo que todo lo que necesita hacer es compilar global.resx y agregar sus dll (2 dlls) a su carpeta bin y funcionará!

Khaled
fuente