【问题标题】:How can I get the line number which threw exception?如何获取引发异常的行号?
【发布时间】:2011-03-20 17:30:57
【问题描述】:

catch 块中,如何获取引发异常的行号?

【问题讨论】:

标签: c# exception


【解决方案1】:

如果您需要的不仅仅是从 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 文件时才有效。

【讨论】:

  • ?(New StackTrace(ex, True)).GetFrame(0).GetFileLineNumber() 用于来自即时窗口的 VB 单行。
  • C# 一班:int line = (new StackTrace(ex, true)).GetFrame(0).GetFileLineNumber();
  • 这总是为我返回 0。这是由于没有 pdb 文件造成的吗?它是什么以及如何获得它? (我使用的是 ASP.net)
  • 为什么要使用 GetFrame(0)?我认为您应该使用 GetFrame(FrameCount-1)。
  • 我发现@DewaldSwanepoel 建议使用GetFrame(st.FrameCount-1) 更可靠。
【解决方案2】:

简单的方法,使用Exception.ToString()函数,它会返回异常描述后面的行。

您还可以检查程序调试数据库,因为它包含有关整个应用程序的调试信息/日志。

【讨论】:

  • 嗯,MSDN 的想法不同,它“创建并返回当前异常的字符串表示形式”:msdn.microsoft.com/en-us/library/…
  • 你会得到类似于:System.Exception: Test at Tests.Controllers.HomeController.About() in c:\Users\MatthewB\Documents\Visual Studio 2013\Projects\Tests\Tests\Controllers\HomeController.cs:line 22
  • 这应该是公认的答案。我总是去找 ex.message,想知道为什么愚蠢的 VB.net 无法获得与 Java 相同的信息。
  • 这个答案没有更多的赞成票真是太疯狂了。这很简单,工作可靠,并且没有 PDB 警告。
  • Exception.Message 对我来说已经死了。再也不会了。
【解决方案3】:

如果您没有.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;
    }
}   

【讨论】:

  • 不幸的是,在非英语操作系统中不起作用(“行”字取决于语言环境)。
  • @KvanTTT 你可以使用Regex.Match:[^ ]+ (\d+) 来达到同样的效果。
  • 这个答案对我不起作用,因为 ex.StackTrace 没有 :line 并且我没有 PDB 文件。
【解决方案4】:

您可以包含与程序集关联的 .PDB 符号文件,其中包含元数据信息,并且当抛出异常时,它将在堆栈跟踪中包含此异常起源的完整信息。它将包含堆栈中每个方法的行号。

【讨论】:

  • 如何包含一个 PDB?有没有办法将 PDB 捆绑到应用程序中/将其注册到 GAC?
【解决方案5】:

检查这个

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();

【讨论】:

    【解决方案6】:

    我为 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);
    
        }
    }
    

    【讨论】:

      【解决方案7】:

      更新答案

          // 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();
      

      【讨论】:

        【解决方案8】:

        我尝试使用@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# 中适用于我。

        【讨论】:

          【解决方案9】:

          扩展方法

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

          【讨论】:

            【解决方案10】:

            如果生成异常的库是使用调试符号编译的,则行号将包含在堆栈跟踪中。这可以是单独的文件 (*.pdb) 或嵌入到库中。

            对于 .NET Core、.NET 5 及更高版本,要在发布版本中具有完整的异常行号,请按如下方式配置项目:

            <PropertyGroup>    
              <DebugSymbols>true</DebugSymbols>
              <DebugType>embedded</DebugType>
            
                <!-- Only enable the following if the line numbers mismatch -->
                <!--<Optimize>false</Optimize>-->
                
                <!--
                  Additional properties which may impact how printed line numbers match the source code line numbers are listed here:
                  https://docs.microsoft.com/en-us/dotnet/core/run-time-config/compilation
                -->
            </PropertyGroup>
            

            上面的配置将直接在构建的文件中包含调试符号,可以作为nugets发布。

            上述方法的替代方法是将调试包与主要的 nuget 包一起恢复,目前尚不支持:https://github.com/NuGet/Home/issues/9667

            现在获取异常行号:

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

            【讨论】:

              【解决方案11】:

              为我工作:

              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();
              

              【讨论】:

                【解决方案12】:

                如果您的堆栈跟踪大于 1,则应该是:

                var st = new StackTrace(es, true);
                // Get the top stack frame
                var frame = st.GetFrame(st.FrameCount - 1);
                

                // 从栈帧中获取行号 var line = frame.GetFileLineNumber();

                【讨论】:

                  【解决方案13】:

                  在 Global.resx 文件中有一个名为 Application_Error 的事件

                  只要发生错误就会触发,您可以轻松获取有关错误的任何信息,并将其发送到错误跟踪电子邮件。

                  另外我认为你需要做的就是编译 global.resx 并将它的 dll(2 个 dll)添加到你的 bin 文件夹中,它会起作用!

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2011-04-17
                    • 2016-11-14
                    • 2018-11-14
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多