Как получить номер строки ошибки кода с помощью try-catch

Я хочу получить номер строки кода, вызывающий ошибку. Например:

static void Main(string[] args)
{
    using (SqlConnection conn = new SqlConnection(bagcum))
    {
        SqlCommand cmd = conn.CreateCommand();
        cmd.CommandText = "DONTINSERT into GIVEMEERROR(CamNo,Statu) values (" + 23 + "," + 0 + ")";
        conn.Open();
        int n = cmd.ExecuteNonQuery();
    }
}

Так как мы знаем, что код не работает, он будет вызывать исключение. Номер строки кода, который:

int n = cmd.ExecuteNonQuery();

Итак, как можно получить номер строки с помощью try-catch? Я попытался использовать класс StackTrace, но он дает номер строки как 0:

static void Main(string[] args)
{
    try
    {
        using (SqlConnection conn = new SqlConnection(bagcum))
        {
            SqlCommand cmd = conn.CreateCommand();
            cmd.CommandText = "DONTINSERT into GIVEMEERROR(CamNo,Statu) values (" + 23 + "," + 0 + ")";
            conn.Open();
            int n = cmd.ExecuteNonQuery();
        }        
    }
    catch (Exception ex)
    {
        System.Diagnostics.StackTrace trace = new System.Diagnostics.StackTrace(ex, true);            
        Console.WriteLine("Line: " + trace.GetFrame(0).GetFileLineNumber());
    }
}

ВЫВОД:

Line:0

Обновление:
Обычно строка ошибки составляет 22, поэтому я должен получить это число.

Спасибо

Ответ 1

Попробуйте этот простой хак:

Сначала добавьте этот класс (расширение) в пространство имен (наиболее подходящим для класса):

public static class ExceptionHelper
{
    public static int LineNumber(this Exception e)
    {

        int linenum = 0;
        try
        {
            //linenum = Convert.ToInt32(e.StackTrace.Substring(e.StackTrace.LastIndexOf(":line") + 5));

            //For Localized Visual Studio ... In other languages stack trace  doesn't end with ":Line 12"
            linenum = Convert.ToInt32(e.StackTrace.Substring(e.StackTrace.LastIndexOf(' ')));

        }


        catch
        {
            //Stack trace is not available!
        }
        return linenum;
    }
}

И его сделать! Используйте метод LineNumber всякий раз, когда вам это нужно:

try
{
//Do your code here
}
catch (Exception e)
{
int linenum = e.LineNumber();
}

Ответ 2

попробуйте это

Чтобы получить номера строк в StackTrace, вам нужно иметь правильную отладочную информацию (файлы PDB) вместе с вашими dll/exes. Чтобы сгенерировать информацию об отладке, установите параметр в Project Properties -> Build -> Advanced -> Debug Info:

alt text

Установка его в full должна быть достаточной (см. документы MSDN, что и другие варианты). Информация об отладке (то есть файлы PDB) генерируется для конфигураций сборки Debug по умолчанию, но также может быть сгенерирована для конфигураций сборки Release.

Генерирование PDB для релизных сборок позволяет вам отправлять вам код без PDB, но для отказа от PDB рядом с DLL, если вам нужны номера строк (или даже для подключения удаленного отладчика). Следует отметить, что в сборке релизов номера строк могут быть не совсем корректными из-за оптимизаций, сделанных компилятором или компилятором JIT (это особенно важно, если номера строк отображаются как 0).

Ответ 3

Проблема заключается в том, что вы пытаетесь получить номер строки первого кадра исключения:

System.Diagnostics.StackTrace trace = new System.Diagnostics.StackTrace(ex, true);
Console.WriteLine("Line: " + trace.GetFrame(0).GetFileLineNumber());

Однако исключение не возникает в строке, которую вы пишете ExecuteNonQuery, но где-то внутри этой функции, возможно, несколько кадров стека (т.е. вложенных вызовов функций) глубже. Таким образом, первый кадр (который вы явно извлекаете с помощью GetFrame(0)) находится где-то внутри кода Microsoft (скорее всего, System.Data.dll), для которого у вас нет отладочных символов.

Выпишите полное исключение stacktrace в своей функции, чтобы увидеть, что я имею в виду:

try
{
   // your code ...
}
catch (Exception ex) 
{
   Console.WriteLine(ex);
}

Недостаточно синтаксического анализа stacktrace (т.е. ex.StackTrace), нет надежного способа получить имя строки вызова ExecuteNonQuery(). Я бы особенно не попытался подсчитать стековые кадры вверх по стеку, где происходит ваш вызов ExecuteNonQuery().

Интересно, однако, что вам нужен единственный linenumber для, почему бы просто не записывать/печатать/независимо от того, что представляет собой полный стек. По крайней мере, по причинам диагностики, которые намного полезнее.

Ответ 4

Вы можете использовать класс System.Diagnostics.StackTrace, как показано ниже:

public void MethodName()
{
    try
    {
        throw new Exception();
    }
    catch (Exception ex)
    {
        // Get stack trace for the exception with source file information
        var trace = new StackTrace(ex, true);

        // Get the top stack frame
        var frame = trace.GetFrame(0);

        // Get the line number from the stack frame
        var line = frame.GetFileLineNumber();
    }
}

Ответ 5

Вы можете получить 0 в результате, если вы не инициализируете StackTrace для включения fileinfo.

enter image description here

Попробуйте это

try
{
    //code
}
catch (Exception e)
{
    var lineNumber = new System.Diagnostics.StackTrace(e, true).GetFrame(0).GetFileLineNumber();
}

Это сработало для меня.

Ответ 6

Здесь довольно простой способ получить кучу информации из объекта Exception: просто добавьте такой код к любым потенциальным методам исключения:

catch (Exception ex)
{
    String exDetail = String.Format(ExceptionFormatString, ex.Message, Environment.NewLine, ex.Source, ex.StackTrace);
    MessageBox.Show(exDetail);
}

Информация, которую вы получаете, часто будет более конкретной, особенно в отношении номеров строк, где возникают проблемы, чем вы могли бы видеть.

Возможно, вы заметили, что String.Format() использует константу, а именно "ExceptionFormatString". Это хорошая практика, поэтому, если вы хотите ее изменить, добавив вышеприведенный код в 40-eleven methods, вы можете просто изменить его на одно место. В любом случае, вот он:

public static readonly String ExceptionFormatString = "Exception message: {0}{1}Exception Source: {2}{1}Exception StackTrace: {3}{1}";

Счастливая отладка!

Ответ 7

Чтобы получить номера строк, вам нужно, чтобы ваше приложение находилось в режиме отладки или включало символы отладки в той же папке (файл .pdb) для отображения номеров строк. Затем вы создаете код, как указано, и должны работать.

Ответ 8

следующий метод обработчика журнала ошибок кода отлично работает:

в catch:

 catch (Exception ex)
            {
                CommonTools.vAddToLog(ex, EmpID, ErrorCodes.UnDefined);
                Response.Redirect("~/ErrorPage.aspx");
            }

в методе AddToLog:

 string _exMsgErr = string.Empty;
                var frame = oStackTrace.FrameCount > 1 ? oStackTrace.GetFrame(1) : oStackTrace.GetFrame(0);
                if (oException.GetType() == typeof(JOVALException))
                {
                    JOVALException _JOVALEx = (JOVALException)oException;
                    _exMsgErr = _JOVALEx.Message;
                }
                else
                {
                    _exMsgErr = oException.Message;
                }
                ErrorLog oError = new ErrorLog(frame.GetMethod().Name, (string)frame.GetFileName(), (int)frame.GetFileLineNumber(), sCustomErrorMessage == string.Empty ? _exMsgErr : sCustomErrorMessage, sUserID, oErrCode);
                //Cont. your code of log file

Наконец, файл журнала xml выглядит следующим образом:

<ErrorLog>
<MethodName>FillRolesDDLs</MethodName>
<FileName>
F:\Projects\ERP\ERP\Pages\SystemSettings\Roles.aspx.cs
</FileName>
<LineNumber>61</LineNumber>
<ErrorMesssage>
The given DataRow is not in the current DataRowCollection.
</ErrorMesssage>
<UserID>1</UserID>
<ErrCode>UnDefined</ErrCode>
<Time>15/03/2015 16:23:21.976</Time>
</ErrorLog>

Ответ 9

В .NET 4.5 вы можете использовать ExceptionDispatchInfo, чтобы изменить ваши исключения вместо классического throw; (убедитесь, что PDB файлы есть или номера строк не будут отображаться):

    static void A()
    {
        try
        {
            throw new Exception("A");
        }
        catch (Exception e)
        {
            ExceptionDispatchInfo.Capture(e).Throw();
        }
    }

Источник: blogpost. Файлы PDB не уменьшают производительность в Windows.

Ответ 10

Скопируйте всю трассировку стека в строку или stringbuilder с помощью try/catch, который может быть брошен, см. ниже пример

try
{
    //Do some programming
}
catch(Exception ex)
{

   //Catch the exception and assign the stack trace
   StackTrace = ex;
}

Выход будет

System.IndexOutOfRangeException: Index was outside the bounds of the array.   
at Program.Run() in C:\Console Application1\Program.cs:line 37    
at Program.Main(String[] args) in C:\Console Application1\Program.cs:line 45 

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