FXCop自定义规则,用于检测catch是否具有日志记录(自定义代码分析)

时间:2015-04-29 20:25:14

标签: c# fxcop-customrules

我已经实施了几个“股票”Microsoft Code Analysis规则。然而,他们缺少一个区域,他们没有在捕获中检测到是否实施了日志记录。

所以我的测试项目有这两种方法。我希望看到其中一个提高我的自定义错误,而另一个通过。

public void CatchTestNoLogging()
{
   try
   { string A = "adsf"; }
   catch (Exception ex)
   { throw; }
 }

 public void CatchTestLogging()
 {
    try
    { string A = "adsf"; }
    catch (Exception ex)
    { 
       log.Error("Test Error");
       throw;
     }
  }

我的自定义规则能够检测是否有捕获但我无法看到我如何检测是否使用了记录?

这是自定义规则的SNIP:

if (iList[i].OpCode == OpCode._Catch)
{
   isCatchExists = true; //this gets hit as I want
   //so the question is what can I do to detect if logging is implemented in the catch?
}

快速指示我访问的方式会很棒。 谢谢

1 个答案:

答案 0 :(得分:0)

那么,

这不完美,但这就是我所得到的。我知道/有一个来自谷歌的框架如何寻找一个阻止块...那就是我需要的一半所以我从那里开始,代码看起来像这样:

if (item.OpCode == OpCode._Catch)
{
   isCatchExists = true;
}

所以我在调试器中进行了操作,看看与没有日志记录相比,日志记录(log4net)看起来是什么样的,看看是否有些东西跳出来了。好吧,我确实找到了这个:

Side by Side

探索log4net对象我看到了:

enter image description here

所以我没有看到确定log.error在catch中的方法,但我可以确定是否存在一个。所以我写了这个:

public override ProblemCollection Check(Member member)
{
   Method method = member as Method;

   bool isCatchExists = false;
   bool isLogError = false;

   if(method != null)
   {
      //Get all the instrections of the method.
      InstructionCollection iList = method.Instructions;

      foreach (Instruction item in iList)
      {
         #region Check For Catch

         if (item.OpCode == OpCode._Catch)
         {
            isCatchExists = true;
         }

         #endregion

         #region Check for Error Logging (log4net)

         if (item.Value != null)
         {

             if (item.OpCode == OpCode.Callvirt && item.Value.ToString() == "log4net.ILog.Error")
             {
               isLogError = true;
             }
         }

         #endregion

      }


      if (isCatchExists && !isLogError)
      {
        Problems.Add(new Problem(this.GetNamedResolution("AddLogging", member.FullName)));
      }
    }
        return this.Problems;
 }

这有效,但有一些警告。

  1. 这是硬编码到log4net。 一个。我不喜欢硬代码,但我可能会为其他日志记录方法添加不同的规则。

  2. 我无法确定log.error是否在catch块中。 一个。所以一个人可以在try块中有一个log.error,我的规则会通过它。