Как я могу получить номер строки, которая вызвала исключение?


198

В catchблоке, как я могу получить номер строки, которая вызвала исключение?


во время выполнения нет исходного кода. для чего эта строка не будет использоваться? во время отладки среда IDE четко показывает строку, которая выдает исключение.
ankitjaininfo



@ankitjaininfo не поможет, если нет IDE!
Майкл

Отвечает ли это на ваш вопрос? Показать номер строки в обработке исключений
Liam

Ответы:


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
? (New StackTrace (ex, True)). GetFrame (0) .GetFileLineNumber () для отдельной строки VB из непосредственного окна.
Джонатан

34
C # один лайнер: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

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

2
@KvanTTT Вы можете использовать Regex.Matchс :[^ ]+ (\d+)тем же эффектом.
Дэн

Этот ответ не работает для меня, так как ex.StackTrace не имеет, :line и у меня нет файла PDB.
Воинственный шимпанзе

18

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


Как можно было бы включить PDB? Есть ли способ включить 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

Я добавил расширение Exception, которое возвращает строку, столбец, метод, имя файла и сообщение:

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 dll) в папку bin, и это будет работать!

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.