【问题标题】:Show line number in exception handling在异常处理中显示行号
【发布时间】:2010-10-15 20:35:21
【问题描述】:

如何显示导致错误的行号,这甚至可以通过 .NET 编译其 .exe 的方式实现吗?

如果没有,Exception.Message 是否有一种自动方式来显示出错的子?

try
{
  int x = textbox1.Text;
}
catch(Exception ex)
{
     MessageBox.Show(ex.Message);
}

【问题讨论】:

标签: c# .net exception exception-handling line-numbers


【解决方案1】:

使用ex.ToString() 获取完整的堆栈跟踪。

即使在发布模式下,您也必须使用调试符号(.pdb 文件)进行编译,以获取行号(这是项目构建属性中的一个选项)。

【讨论】:

  • 如果它是一个 Web 项目并且您想将 pdb 部署到服务器 - 在 Package/Publish Web 部分的项目选项中取消选中“排除生成的调试符号”。
  • 有人能解释一下“用调试符号编译”吗?我的项目有“定义调试常量”、“定义跟踪常量”和“调试信息:完整”,但我没有得到行号。 MSDN 说,“单击属性页左窗格中的 Build 选项卡,然后选中要启用的编译器设置的复选框。清除要禁用的设置的复选框。”很有帮助。
  • 只有当我取消选中优化代码时,它才能在发布模式下工作
【解决方案2】:

要查看给定异常的堆栈跟踪,请使用e.StackTrace

如果您需要更详细的信息,可以使用System.Diagnostics.StackTrace 类(这里有一些代码供您尝试):

try
{
    throw new Exception();
}
catch (Exception ex)
{
    //Get a StackTrace object for the exception
    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();
}

这仅在有可用于程序集的 pdb 文件时才有效。查看项目属性 - 构建选项卡 - 高级 - 调试信息选择以确保存在 pdb 文件。

【讨论】:

  • 为什么会得到第一个堆栈帧?您不想对最后一个堆栈帧感兴趣吗?即 StackFrame frame = st.GetFrame(st.FrameCount - 1)
  • 我尝试在 WCF Web 服务中使用它,它返回的行号始终为 0。这是在存在 .pdb 文件的调试模式下。
  • 我在让我的 DLL 加载 PDB 文件时遇到问题 - 我只需要确保它们位于同一目录中吗?
【解决方案3】:

如果您使用 'StackTrace' 并将 .pdb 文件包含在工作目录中,则堆栈跟踪应包含行号。

【讨论】:

    【解决方案4】:
    string lineNumber=e.StackTrace.Substring(e.StackTrace.Length - 7, 7);
    

    【讨论】:

      【解决方案5】:

      这样你就可以从异常中获取行号

      public int GetLineNumber(Exception ex)
      {
      
          const string lineSearch = ":line ";
          var index = ex.StackTrace.LastIndexOf(lineSearch);
          int ln=0;
          if (index != -1)
          {
      
      
              var lineNumberText = ex.StackTrace.Substring(index + lineSearch.Length);
              string lnum = System.Text.RegularExpressions.Regex.Match(lineNumberText, @"\d+").Value;
              int.TryParse(lnum,out ln);
      
          }
          return ln;
      }
      

      【讨论】:

        【解决方案6】:

        如果生成异常的库是使用调试符号编译的,则行号将包含在堆栈跟踪中。这可以是单独的文件 (*.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();
        }
        

        【讨论】:

          猜你喜欢
          • 2010-12-26
          • 1970-01-01
          • 1970-01-01
          • 2013-01-09
          • 2021-06-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多