C#中的.NET程序集验证?

4

如何检查已加载的程序集是否是有效的.NET程序集?我目前有这段代码,但非托管的DLL会抛出BadImageFormatException异常。

string[] filepaths = Directory.GetFiles(Directory.GetCurrentDirectory(), "*.dll", SearchOption.AllDirectories);
List<Type> potentialEffects = new List<Type>();

foreach (string filepath in filepaths)
{
    Assembly a = Assembly.LoadFile(filepath);
    potentialEffects.AddRange(a.GetTypes());
}
8个回答

11

尝试捕获异常会降低程序运行速度,想知道是否可以使用条件语句。 - Euclid
9
欧几里得:你在进行微观优化。与实际加载相比,抛出“BadImageFormatException”的成本微不足道。 - Mehrdad Afshari
1
有一种方法需要使用P/Invoke(也很慢)。在MSDN博客上有一篇非常好的文章:http://blogs.msdn.com/suzcook/archive/2004/03/17/determining-whether-a-file-is-an-assembly.aspx - Sebastian P.R. Gingter
此外,另一种选择是解析PE格式并检查CLR头,这在性能方面也不是一个廉价的操作。与捕获BadImageFormatException相比,开销也非常大。 - Wim
捕获异常非常简洁和容易。除非性能对你来说是一个重大问题,否则这是一个不用思考的选择。 - Paul Turner
try-catch在一般情况下速度较慢,但通常只有在需要频繁使用时才会成为问题。即便如此,这似乎可能是证明规则的例外(没有恶意)。您计划加载多少程序集?简单性本身就有价值。 - Jim L

4

我有一段代码,可以检查一个文件是否为PE文件和托管程序集。使用起来非常简单:

var files = Directory.GetFiles (
    Directory.GetCurrentDirectory (),
    "*.dll", SearchOption.AllDirectories);

var potentialEffects = new List<Type> ();

foreach (var file in files) {
    if (!Image.IsAssembly (file))
        continue;

    var assembly = Assembly.LoadFile (filepath);
    potentialEffects.AddRange (assembly.GetTypes ());
}

就性价比而言,我的机器上进行的一项小基准测试表明,与异常Assembly.LoadFrom触发相比,它的速度快了两倍。另一方面,在有效情况下,它会损失一些时间。因此,这是一个计时平均情况的问题。


2
例外情况是验证程序集的最佳方法。
请记住,在加载程序集时,不仅进行管理/非托管检查。还可能进行签名检查、平台检查(32位与64位)。这些也可能导致异常抛出。
你最好让框架来完成它的工作。
如果你正在加载作为附加系统一部分的托管代码(因此你正在查看文件夹中的所有dll),那么我建议你选择一个命名约定,或者使用一个单独的插件文件夹,其中你不希望找到非托管代码。


1

一个未被托管的 DLL 不是一个有效的 .NET 程序集。尝试加载该“程序集”,并在失败时捕获异常。如果没有抛出异常,就可以继续进行。


1
如果您想从C#中进行检查,可以添加Try Catch。
或者,您可以使用随 .net框架提供的peverify.exe工具来确定一个dll是否是有效的程序集。

启动一个 peverify 进程(它仅随 SDK 一起提供,而不随可再分发文件一起提供)似乎对于这种类型的测试来说有点过重了 :) - Jb Evain

0

-2

看一下Activator类。

将这个技术放在try/catch块中可以帮助您捕获各种无效类型,不仅限于.NET程序集,还包括许多其他运行时违规。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接