【问题标题】:How to get error line number of code using try-catch如何使用 try-catch 获取代码的错误行号
【发布时间】:2011-12-01 08:39:17
【问题描述】:

我想获取导致错误的代码行号。例如;

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,所以我必须得到那个数字。

谢谢

【问题讨论】:

  • 如果您处于RELEASE 模式,则堆栈跟踪中不再存在行号(以及其他行号)。在DEBUG 模式下编译的最简单方法。如果仍然无法正常工作,请检查 project properties\Advanced\Debug Info 中是否有完整的 Debug 信息。
  • @JiBéDoublevé 处于调试模式,完全调试
  • 您的 .pdb 文件是否与所有其他文件位于同一目录中?

标签: c# exception


【解决方案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();
}

【讨论】:

  • 我也有这个问题。并通过问题代码返回 0。并通过您的代码获取 'e)' :( 我在一个父类中管理异常。请您帮帮我。
【解决方案2】:

试试这个

要获取 StackTrace 中的行号,您需要在 dll/exe 旁边拥有正确的调试信息(PDB 文件)。要生成调试信息,请设置Project Properties -> Build -> Advanced -> Debug Info中的选项:

将其设置为full 就足够了(请参阅MSDN docs 了解其他选项的作用)。调试信息(即 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),您没有任何调试符号。

    在你的函数中写出完整的异常堆栈跟踪,看看我的意思:

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

    没有解析堆栈跟踪(即 ex.StackTrace),没有可靠的原因获取“ExecuteNonQuery()”调用的行号。我特别会尝试在您调用 ExecuteNonQuery() 的堆栈中向上计数堆栈帧。

    但是,我想知道,您需要唯一的行号来做什么,为什么不直接记录/打印/任何完整的堆栈跟踪。至少出于诊断原因,无论如何这更有用。

    【讨论】:

      【解决方案4】:

      如果您不初始化 StackTrace 以包含文件信息,则结果可能为 0。

      试试这个

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

      这对我有用。

      【讨论】:

        【解决方案5】:

        你可以使用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();
            }
        }
        

        【讨论】:

          【解决方案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-11 方法之后,你可以只改变一个地方。无论如何,这里是:

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

          调试愉快!

          【讨论】:

            【解决方案7】:

            要获取行号,您需要您的应用程序处于调试模式在同一文件夹(.pdb 文件)中包含调试符号以显示行号。您发布的代码应该可以工作。

            【讨论】:

              【解决方案8】:

              以下代码异常日志处理方法工作正常:

              赶上

               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。 Windows 上的 PDB 文件 don't decrease performance

                【讨论】:

                  【解决方案10】:

                  使用可以抛出的 try/catch 将整个堆栈跟踪复制到字符串或 stringbuilder 中,请参见下面的示例

                  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 
                  

                  第一行显示异常的类型和消息。第二行显示抛出异常的文件、函数和行号

                  【讨论】:

                  • 好吧,这似乎是一个解决方案,但我在不解析任何输出的情况下询问
                  • 没有足够的代码,我无法获取 StackTrace = ex;去工作。 -1 表示非工作示例。
                  猜你喜欢
                  • 2012-11-15
                  • 2018-09-24
                  • 2019-05-19
                  • 2011-02-15
                  • 1970-01-01
                  • 1970-01-01
                  • 2011-08-13
                  • 1970-01-01
                  • 2016-06-06
                  相关资源
                  最近更新 更多