zoukankan      html  css  js  c++  java
  • 如何在记录异常日志的时候包含源代码文件名和行号等信息

    前言

    作为一个程序员,你的相当一部分时间可能会用在调试。不知道大家是否同意,异常处理(Exception Handling)是一个看似简单,但是又极难做好的工作。当然,现在已经有一些业界经验以及框架(例如Enterprise Library中的Exception Handling Application Block)可供参考和使用,这些框架可以帮助我们较为灵活地配置,处理或者记录异常。我今天要跟大家分享的一个话题是,如何在记录异常的时候,包含源代码文件名和行号等有用信息。如果有这些信息,我们将能更加简单地定位到问题所在。

    案例演示

    为了讲解这个内容,我准备了一个简单的项目来做演示,如下所示

    image

    实际上,这个Solution中有两个项目,一个是作为组件的ClassLibrarySample

       1:  using System;
       2:   
       3:  namespace ClassLibrarySample
       4:  {
       5:      public class Test
       6:      {
       7:          public void MyMethod(int a, int b) {
       8:              try
       9:              {
      10:                  Console.WriteLine(b/a);
      11:              }
      12:              catch (Exception ex)
      13:              {
      14:                  Console.WriteLine(ex.Message);
      15:              }
      16:          }
      17:      }
      18:  }
     

    另一个是作为调用程序的ConsoleApplicationSample

       1:  using System;
       2:   
       3:  namespace ConsoleApplicationSample
       4:  {
       5:      class Program
       6:      {
       7:          static void Main(string[] args)
       8:          {
       9:              var t = new ClassLibrarySample.Test();
      10:              t.MyMethod(0, 1);//这个调用会出错,因为会发生除零错误
      11:              Console.Read();
      12:          }
      13:      }
      14:  }

    这个程序运行起来肯定就是会报告异常,然后被捕捉到,我们在主程序上面可以看到如下的输出

    image

    我们都知道,这样的异常消息可能对我们帮助不是很大,尤其是如果源文件中代码有成百上千行,那么如果不能快速定位到可能是哪一行出了这个异常,那么看起来调试和排错都会很难。

    那么是否有办法在异常消息中,得到源代码文件的一些信息呢?事实上是可以做到的,你只要像下面这样修改即可:使用了StackTrace这个类型

       1:  using System;
       2:  using System.Diagnostics;
       3:   
       4:  namespace ClassLibrarySample
       5:  {
       6:      public class Test
       7:      {
       8:          public void MyMethod(int a, int b) {
       9:              try
      10:              {
      11:                  Console.WriteLine(b/a);
      12:              }
      13:              catch (Exception ex)
      14:              {
      15:                  Console.WriteLine(ex.Message);
      16:                  //通过如下代码来记录异常详细的信息
      17:                  var trace = new StackTrace(ex, true).GetFrame(0);
      18:                  Console.WriteLine("文件名:{0},行号:{1},列号:{2}", trace.GetFileName(), trace.GetFileLineNumber(), trace.GetFileColumnNumber());
      19:              }
      20:          }
      21:      }
      22:  }

    这样一来,我们再进行调试的时候,就可以看到更加详细的信息了。

    image

    大家可能会很好奇,这个信息是怎么给我们的呢?其实,要想实现这个功能,必须满足一个前提条件,就是必须有ClassLibrarySample这个组件对应的调试符号文件(pdb)。

    image

    如果我将这个文件删除掉,会怎么样呢?

    image

    我们看到,如果没有pdb文件,则输出的信息是空白的。

    所以,如果你想使用这个技术来记录这些与源代码有关的详细信息,需要确保在部署应用程序的时候,将有关组件的pdb文件也一起部署

    如果是私有部署的话,那么要做到这一点是不难的,打包的时候,将pdb文件一起包含进去就可以了。但如果这个组件是公有部署(部署到GAC) 的话,就需要额外的一些步骤。

    为了将程序集部署到GAC,我们首先需要对其进行强名称签名。

    image

    然后,通过gacutil这个命令行工具,可以手工地将其添加到GAC中

    image

    接下来,为了让主程序使用GAC中这个组件,而不是程序根目录下面的那个。我们需要对引用做一个设置:Copy local设置为false

    image

    再次运行主程序的话,我们会得到如下的输出

    image

    还是没有与源代码有关的详细信息,这是因为注册到GAC的程序集默认都是没有pdb文件的。他们一般在下面这样的目录里面

    image

    【备注】.NET Framework 4.0这个版本中对于GAC的路径做了调整,不再是原先的c:windowsassembly目录了

    所以,如果需要的话,你可以将pdb文件,手工(或者通过脚本)复制到这个目录,例如

    image

    这样的话,就可以在运行主程序的时候,得到与源代码有关的详细信息了。

    image

  • 相关阅读:
    第一周例行报告psp
    作业要求 2018091-2 博客作业
    20181011-1第一周例行报告
    20180912-2第一周博客作业
    Elasticsearch
    centos7 安装Hadoop-2.6.0-cdh5.16.1.tar.gz
    centos7安装hadoop2.7.7
    centos7安装jdk8
    专业知识4
    专业知识3
  • 原文地址:https://www.cnblogs.com/chenxizhang/p/3185702.html
Copyright © 2011-2022 走看看