如何识别重复的程序集?

问题描述:

虽然我正在查看关于MEF的一些问题,但我偶然发现了this particular answer的问题。这让我想起了这么一点,因为我从来没有尝试过这样做,但在这个问题的场景中可以看到它非常有效。如何识别重复的程序集?

场景: 如果你有不同的.NET程序集的目录中的所有命名不同,你会怎么能够识别那些可以是相同的,但改名(即复制MyAssembly.dll程序VS MyAssembly.dll程序) ?

我能想到以下项目:

  1. 检查文件大小(应该是相同的)

  2. 检查程序集版本号

  3. 循环通过该组件使用反射和尝试找出差异。

是否有解决此问题的任何其他/更简单的方法?是否有其他标准来查看确定2个不同名称的DLL实际上是否是相同的编译程序集?

+0

@james,你说你真的在寻找一个程序化的解决方案。检查代码,这是否会更接近?让我们知道我们可以改进的地方。 – Abel 2009-11-17 19:57:10

+0

@Abel我希望今晚能测试一下。我无法像我希望昨晚那样,希望今晚我能知道更多。今晚会让你知道/标记一个答案。 – JamesEggers 2009-11-17 20:24:41

起初我以为你可以用EqualsReferenceEquals来做到这一点,但这个证明太容易出错。例如,如果您使用Assembly.LoadFile,则这不起作用。

随着nUnit,我做了下面的测试,这些测试有点基本,但给你一些继续。加载类型的方式很奇怪(请参阅MSDN)。我假设你知道如何做“快速测试”,以防你想检查二进制等,等等(见下面的PS)。

Assembly asm1 = Assembly.LoadFile(@"someDebugAssembly.dll"); 
Assembly asm2 = Assembly.LoadFile(@"someReleaseAssembly.dll"); 

// load all the types (the double try/catch is on purpose) 
Type[] types1 = null 
Type[] types2 = null; 
try 
{ 
    types1 = asm1.GetTypes(); 
} 
catch (ReflectionTypeLoadException e) 
{ 
    types1 = e.Types; 
} 
try 
{ 
    types2 = asm1.GetTypes(); 
} 
catch (ReflectionTypeLoadException e) 
{ 
    types2 = e.Types; 
} 

// same length 
Assert.AreEqual(types1.Length, types2.Length); 

// check each type 
IEnumerator types1Enumerator = types1.GetEnumerator(); 
types1Enumerator.Reset(); 
foreach (Type t in types2) 
{ 
    types1Enumerator.MoveNext(); 
    Assert.AreEqual(types1Enumerator.Current, t); 
} 

关于代码的说明:这种比较方法将两个包含相同类型的程序集视为相等。这意味着调试和发布版本,或不同的版本,都没有考虑在内。使用asm1.GetName()及其属性(再次:不要使用Equals!)来比较各个字符串(版本,全名等)。 PS:定义什么构成两个相等的组件是有趣的,:

  1. 它们是二进制等于
  2. 有版本,完全合格的名称是相等的
  3. 强名称相同
  4. 所有类型,深受相比,具有相同的签名

视你选择什么,两个完全不同的程序集(即调试版本与发布版本)可以相同。这真的取决于你想如何比较。

更新:纠正以前的错误,并添加代码示例

+0

取决于你如何加载它们http://blogs.msdn.com/suzcook/archive/2003/05/29/57143.aspx – erikkallen 2009-11-16 18:15:45

+0

@erik:对,我在测试时得出了相同的结论。我在编辑答案。 – Abel 2009-11-16 18:24:03

我会先使用第1点和第2点进行简单的快速检查,即检查文件大小和程序集版本号。如果它们完全不同,那就完成了。

如果不是,请保留具有相同文件大小/版本的文件并计算它们的MD5/SHA1 /无论你喜欢的散列。如果哈希值相同,那么您肯定在同一个程序集中存在两次。由于程序集通常不是很大(最多几兆字节),哈希计算应该足够快。

+1

不,两个组件可能会以相同的散列(鸽子层原理)结束。要完全确定,你必须逐字节比较它们。 – erikkallen 2009-11-16 18:14:47

你也可以使用好老 补偿命令行程序:

c:\tests> comp one.dll two.dll 
Comparing one.dll and two.dll... 
Files compare OK 

更新:更好。下载Windows XP Service Pack 2 support tools,安装它(选择完成安装)。然后进入“运行命令”对话框并输入dupfinder。将它指向您想要的文件夹,您将开始在该路径及其子文件夹中记录所有重复项。

+0

确实在寻找一个.net /程序化的答案,但我没有指定这样的东西,那是我的错。绝对好知道,因为我不知道重复。谢谢 – JamesEggers 2009-11-16 18:23:25

+1

然后我会先比较大小,然后使用类似Mono.Cecil的东西来检查程序集名称/版本/签名(如果签名),而不实际加载程序集。然后,如果程序集没有签名,只需逐字节比较... – Gonzalo 2009-11-16 18:38:19