Як я можу отримати номер рядка, який кинув виняток?


198

Як в catchблоці я можу отримати номер рядка, який викинув виняток?


під час виконання немає вихідного коду. для чого цей рядок не буде використовуватися? під час налагодження IDE чітко показує рядок, який видає виняток.
ankitjaininfo



@ankitjaininfo не корисний, якщо немає IDE!
Майкл

Чи відповідає це на ваше запитання? Показати номер рядка за винятком обробки
Ліам

Відповіді:


281

Якщо вам потрібен номер рядка для більш ніж просто відформатованого сліду стека, який ви отримуєте від Exception.StackTrace, ви можете використовувати клас 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();
}

Зверніть увагу, що це буде працювати лише в тому випадку, якщо для складання доступний файл pdb.


2
? (Нова StackTrace (колишня, правда)). GetFrame (0) .GetFileLineNumber () для одного рядка VB з прямого вікна.
Джонатан

34
C # one лайнер:int line = (new StackTrace(ex, true)).GetFrame(0).GetFileLineNumber();
gunwin

17
Це завжди повертає 0 для мене. Це викликано відсутністю файлу pdb? Що це таке і як його отримати? (Я використовую ASP.net)
Brabbeldas

17
Чому ви використовуєте GetFrame (0)? Я думаю, що ви повинні використовувати GetFrame (FrameCount-1).
Дьюальд Свенпоель

9
Я знайшов пропозицію @DewaldSwanepoel використовувати GetFrame(st.FrameCount-1)набагато надійнішу.
Бред Мартін

75

Простий спосіб, використовуючи Exception.ToString()функцію, вона поверне рядок після опису винятку.

Ви також можете перевірити базу даних налагодження програми, оскільки вона містить інформацію / журнали про налагодження щодо всієї програми.


Ну MSDN думає по- іншому, що він «Створює і повертає строкове представлення поточного виключення»: msdn.microsoft.com/en-us/library / ...
Prokurors

Ви отримуєте щось подібне до:System.Exception: Test at Tests.Controllers.HomeController.About() in c:\Users\MatthewB\Documents\Visual Studio 2013\Projects\Tests\Tests\Controllers\HomeController.cs:line 22
Професор програмування

3
Це має бути прийнятою відповіддю. Я завжди ходив на ex.message і цікавився, чому дурний VB.net не в змозі отримати таку ж інформацію, як у Java.
Маттіс Колі

3
Несумлінно, що ця відповідь не має більшої оцінки. Це просто, працює надійно і не поставляється із застереженнями PDB.
Нік Пентер

9
Exception.Messageдля мене мертвий. Ніколи знову.
Відновіть Моніку Селліо

27

Якщо у вас немає .PBOфайлу:

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

Або як розширення класу Виняток

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
На жаль, не буде працювати в не англійській ОС (слово "рядок" залежить від мови).
Іван Кочуркін

2
@KvanTTT Ви можете використовувати Regex.Matchз :[^ ]+ (\d+)тим же ефектом.
Ден Бешард

Ця відповідь не працює для мене, оскільки у ex.StackTrace немає, :line і у мене немає файлу PDB.
Войовничий шимпанзе

18

Ви можете включити .PDBфайли символів, пов’язані з збіркою, які містять інформацію метаданих, і коли буде викинуто виняток, вона буде містити повну інформацію в стеці сліду, де цей виняток виник. Він буде містити номери рядків кожного методу в стеку.


Як можна було б включити ПТБ? Чи є спосіб поєднати ПТБ у додаток / зареєструвати його в GAC?
Яків Персі


6

Перевірте це

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

Оновлення відповіді

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

Я спробував використовувати рішення by @ davy-c, але мав виняток "System.FormatException:" Введення рядка не було у правильному форматі ". опублікував і придумав:

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

Це працює для мене в VS2017 C #.


0

Спосіб розширення

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

Використання

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

Робота для мене:

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

Я додав розширення до винятку, яке повертає рядок, стовпець, метод, ім'я файлу та повідомлення:

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

У файлі Global.resx є подія під назвою Application_Error

він видається, коли виникає помилка, ви можете легко отримати будь-яку інформацію про помилку та надіслати її на електронну пошту з відстеженням помилок.

Крім того, я думаю, що все, що вам потрібно зробити, це скласти файл global.resx і додати його dll (2 dlls) у вашу папку bin, і це буде працювати!

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.