在C#代码中查找所有文件IO操作(可能通过静态分析)

时间:2015-01-14 10:35:25

标签: c# code-analysis

有没有办法找到调用File.WriteAllTextRequest.Files["filename"].SaveAs("out")等IO操作的所有代码?

现在我可以用所有可能的常见方式来读取/写入类似的文件,例如:

grep 'SaveAs' -I -r . -l | grep "\.cs"

这并不令人满意,因为我无法想到文件可以读写的所有可能方式。也许它可以通过某种方式通过反射或通过分析编译二进制文件中的系统调用来完成?有什么想法吗?

编辑: 如果方法A调用方法B而方法B调用方法C,并且方法C执行文件操作,那么也可以识别该代码。但是,只是为了简化问题,找到直接调用IO就足够了。

3 个答案:

答案 0 :(得分:1)

如果您计划开发此工具,可以启动here

本文介绍了检测程序集和方法依赖关系的方法,因此您可以找到调用IO基元的所有方法,例如FileStream.Write

答案 1 :(得分:1)

所以我一时兴起,决定用Mono.Cecil来尝试。

递归获取方法调用的所有方法的列表非常简单:

static IEnumerable<MethodDefinition> GetMethodsCalledInMethod(MethodDefinition md)
{
    if (md.Body == null)
    {
        return Enumerable.Empty<MethodDefinition>();
    }

    return md.Body.Instructions
        .Select(i => i.Operand)
        .OfType<MethodReference>()
        .Select(mr => mr.Resolve())
        .Where(mr => mr != null);
}

您可以获得要检查的程序集中的所有方法:

var ad = AssemblyDefinition.ReadAssembly(typeof(ATypeInTheAssembly).Assembly.Location);
var allMethodsInAssembly = ad.Modules
    .SelectMany(m => m.Types)
    .SelectMany(t => t.Methods));

然后,您可以通过这个方法调用树递归,直到找到一个看起来像IO调用的方法调用。

Func<MethodDefinition, bool> isFileOperation = md =>
    md.DeclaringType.Name == "FileStream";

这足够吗?我不知道。 File.WriteAllText使用FileStream。您提供的SaveAs示例也是如此。但每个文件访问权限都通过FileStream吗?我不能说。

这种方法也有问题:

  • 你需要注意递归调用,因为否则你的递归会变成一个无限循环,你就会把你的堆栈搞得一团糟。
  • 这是 sloooow 。当我分析一个名为File.WriteAllLines的简单控制台应用程序时,我立即得到了一个结果,但是当我尝试分析分析器本身时,它在树中丢失了。
  • 如果您遇到界面 - 甚至是虚拟方法 - 您无法确定实施的内容,因此您无法知道它是否会执行IO操作与否!

答案 2 :(得分:1)

这取决于你想要在深度分析中做多少。
如果你真的认真地去捕捉所有&#39; System.IO&#39;方法调用我建议使用NRefactory。它是一个前端C#解析器,可以解析C#代码并生成语法树和代码解析器。
关于在code project中使用它的好教程可以帮助您入门。此外,在代码项目教程中,还有一些辅助类,可以让您加载整个解决方案,并为您提供代码解析器。
如果您需要更多样本,可以在blog中找到一些
PS:我会在几个小时内尝试用代码示例扩展这个答案。

相关问题