Comment puis-je obtenir le numéro de ligne qui a déclenché une exception?

198

Dans un catchbloc, comment puis-je obtenir le numéro de ligne qui a levé une exception?

MBZ
la source
au moment de l'exécution, il n'y a pas de code source. à quoi sert cette ligne non? au moment du débogage, l'EDI montre clairement la ligne qui lève l'exception.
ankitjaininfo
doublon possible de la gestion
Fredrik Mörk
@ankitjaininfo n'est pas utile s'il n'y a pas d'IDE!
Michael
Est-ce que cela répond à votre question? Afficher le numéro de ligne dans la gestion des exceptions
Liam

Réponses:

280

Si vous avez besoin du numéro de ligne pour plus que la trace de pile formatée que vous obtenez d'Exception.StackTrace, vous pouvez utiliser 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();
}

Notez que cela ne fonctionnera que si un fichier pdb est disponible pour l'assembly.

Quartermeister
la source
2
? (Nouveau StackTrace (ex, True)). GetFrame (0) .GetFileLineNumber () pour la ligne unique VB à partir de la fenêtre immédiate.
Jonathan
34
C # one liner:int line = (new StackTrace(ex, true)).GetFrame(0).GetFileLineNumber();
gunwin
17
Cela renvoie toujours 0 pour moi. Est-ce dû au fait de ne pas avoir de fichier pdb? Qu'est-ce que c'est et comment l'obtenir? (J'utilise ASP.net)
Brabbeldas
17
Pourquoi utilisez-vous GetFrame (0)? Je pense que vous devriez utiliser GetFrame (FrameCount-1).
Dewald Swanepoel
9
J'ai trouvé que la suggestion d'utilisation de @DewaldSwanepoel GetFrame(st.FrameCount-1)était beaucoup plus fiable.
Brad Martin
75

De manière simple, utilisez la Exception.ToString()fonction, elle renverra la ligne après la description de l'exception.

Vous pouvez également vérifier la base de données de débogage du programme car elle contient des informations / journaux de débogage sur l'ensemble de l'application.

SimpleButPerfect
la source
Eh bien MSDN pense différemment, qu'il « crée et retourne une représentation de chaîne de l'exception actuelle »: msdn.microsoft.com/en-us/library/...
Prokurors
Vous obtenez quelque chose de similaire à:System.Exception: Test at Tests.Controllers.HomeController.About() in c:\Users\MatthewB\Documents\Visual Studio 2013\Projects\Tests\Tests\Controllers\HomeController.cs:line 22
Professeur de programmation
3
Cela devrait être la réponse acceptée. Je suis toujours allé pour ex.message et je me demandais pourquoi stupide VB.net ne pouvait pas obtenir les mêmes informations qu'en Java.
Matthis Kohli
3
C'est fou que cette réponse n'ait pas plus de votes positifs. C'est simple, fonctionne de manière fiable et ne vient pas avec les mises en garde PDB.
Nick Painter
9
Exception.Messageest mort pour moi. Plus jamais.
Rétablir Monica Cellio
27

Si vous n'avez pas le .PBO fichier:

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 comme extensions sur la 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;
    }
}   
radbyx
la source
8
Malheureusement, ne fonctionnera pas dans un système d'exploitation non anglais (le mot "ligne" dépend du lieu).
Ivan Kochurkin
2
@KvanTTT Vous pouvez utiliser Regex.Matchavec :[^ ]+ (\d+)pour le même effet.
Dan Bechard
Cette réponse ne fonctionne pas pour moi, car ex.StackTrace n'en a pas :line et je n'ai pas le fichier PDB.
Warlike Chimpanzee
18

Vous pouvez inclure des .PDBfichiers de symboles associés à l'assembly qui contiennent des informations de métadonnées et lorsqu'une exception est levée, elle contiendra des informations complètes dans la trace de pile de l'origine de cette exception. Il contiendra les numéros de ligne de chaque méthode de la pile.

Darin Dimitrov
la source
Comment procéder pour inclure un PDB? Existe-t-il un moyen de regrouper la PDB dans l'application / de l'enregistrer auprès du GAC?
Jacob Persi
7

Ça marche:

var LineNumber = new StackTrace(ex, True).GetFrame(0).GetFileLineNumber();
Thirisangu Ramanathan
la source
Qu'en est-il des exceptions non gérées? comme UnhandledExceptionEventArgsobjet
Yousha Aleayoub
6

Vérifier celui-ci

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
la source
1

Mise à jour de la réponse

    // 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
la source
1

J'ai essayé d'utiliser la solution By @ davy-c mais j'ai eu une exception "System.FormatException: 'La chaîne d'entrée n'était pas dans un format correct.'", Cela était dû au fait qu'il y avait encore du texte après le numéro de ligne, j'ai modifié le code qu'il posté et est venu avec:

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

Cela fonctionne pour moi dans VS2017 C #.

Joseph Michael
la source
0

Méthode d'extension

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

Usage

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
la source
0

Travailler pour moi:

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
la source
0

J'ai ajouté une extension à Exception qui renvoie la ligne, la colonne, la méthode, le nom de fichier et le message:

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
la source
-3

Dans le fichier Global.resx, il y a un événement appelé Application_Error

il se déclenche chaque fois qu'une erreur se produit, vous pouvez facilement obtenir des informations sur l'erreur et l'envoyer à un e-mail de suivi des bogues.

Je pense aussi que tout ce que vous devez faire est de compiler le global.resx et d'ajouter ses dll (2 dll) à votre dossier bin et cela fonctionnera!

Khaled
la source