如何确定一个“程序集”是否真的发生了改变?

7
我在VS2005中创建了一个简单的“Hello World”应用程序。这是一个直接的控制台应用程序,它只包含以下几行代码:
Console.WriteLine("Hello World");
Console.ReadLine();

当我尝试重新构建相同的控制台应用程序而没有进行任何更改时(只需按下重建按钮),我得到了一个微妙不同的可执行文件。(我从第一个和第二个生成的可执行文件中生成了SHA-1哈希值,它们是不同的!)
为什么没有代码更改时会有所不同?实际上发生了什么变化?我使用十六进制编辑器进行比较,只看到了几个不同的字节。
我想我的最终问题是,我如何知道一个"程序集"是否真的发生了变化?(当然不看文件版本、文件大小等)
编辑
到目前为止,我们已经确定差异在于PE头(时间戳和一些调试数据)。在我重新发明轮子之前,是否有一个"程序集比较"工具可以忽略PE头?
谢谢, Ian
3个回答

6

这些差异将会是:

  • PE头中的时间戳
  • 如果存在,调试数据的GUID

(也许还有其他输出中提到的其他内容?) 要查看这些内容,请在VS命令提示符下运行dumpbin /all /rawdata:none命令。

要正确地执行此操作,您需要编写一个比较工具,了解这些内容并忽略那些字节 - 或者复制可执行文件,清除时间戳和GUID,然后比较这些版本。或者,你可以像controlfreak建议的那样使用fc /b,并假设如果不同的字节数小于20个(时间戳为4个,GUID为16个),则它们可能是相同的。

您可能会使用已清除时间戳的程序集 - 据我所知,它仅用于在其他DLL中缓存导出符号偏移量(如果您连接了该DLL) - 但最好保持原样。如果您实际上需要二进制相同的程序集,则建议更改您的流程,除非确实需要,否则永远不要进行干净的构建。


为了正确地忽略那些字节,我需要知道这些字节的位置和范围,对吧?有没有某种文档可以阅读? - Ian
这是来自 MSDN 的 PE 格式文档链接:http://www.microsoft.com/whdc/system/platform/firmware/PECOFF.mspx。我指的是 COFF 头中的时间戳和调试目录的内容。不过,如果没有现成的工具可以做到这一点,我会非常惊讶 - 不过我不知道有没有这样的工具,抱歉。 - Rup
哇,你做得很好。这是时间戳和一些调试数据!4C4953A4 时间日期戳 Fri Jul 23 16:32:36 2010 4C4953A4 cv 6D 000026E4 8E4 格式:RSDS,{F421268D-98D4-4D76-B70D-9C3E398E5426},1,C:\HelloWorld\HelloWorld\obj\x86\Debug\HelloWorld.pdb*使用 dumpbin /all /rawdata:none - Ian

2

你可以从Visual Studio命令提示符中进行更详细的比较:

  • You could compare the PE header using the output of dumpbin:

    dumpbin /HEADERS assembly.dll
    
  • Or you could compare PE headers and the IL code embedded in the assembly using ildasm:

    ildasm /ALL /TEXT assembly1.dll > dump1.txt
    ildasm /ALL /TEXT assembly2.dll > dump2.txt
    fc dump1.txt dump2.txt        
    

    The /ALL option will dump the DOS and PE headers, the CLR header, assembly metadata and disassembled IL. However, it will not contain embedded resources. If your assmembly contains embedded resources you can use the /OUT option. This will create a separate file for each embedded resource that you can the compare using your favourite diff tool, e.g. WinMerge:

    ildasm /ALL /TEXT /OUT:folder1\dump.txt folder1\assembly.dll
    ildasm /ALL /TEXT /OUT:folder2\dump.txt folder2\assembly.dll
    

0
在命令行中执行以下命令: fc /b

1
这是应该作为一个答案吗?至少提供一些上下文。 - Oded
抱歉哈哈。我加了一些括号,导致机器以为它们是 HTML 标签。 - Matt Phillips
比较文件 a.exe 和 B.EXE 00000088: 92 A4 00000770: F4 DD 00000771: 62 20 00000772: 7F CF 00000773: A1 24 00000774: 0B AA 00000775: 5A 16 00000776: 7A 9A 00000777: 43 41 00000778: B7 9D 00000779: F3 39 0000077A: 22 C0 0000077B: 8D BF 0000077C: 50 82 0000077D: 17 1D 0000077E: 52 27 0000077F: D6 4A 000008CC: 92 A4 000008E8: 2A 8D 000008E9: 6D 26 000008EA: C2 21 000008EB: F0 F4 000008EC: 70 D4 000008ED: 1E 98 000008EE: 3F 76 000008EF: 4B 4D 000008F0: AC B7 000008F1: 5A 0D 000008F2: 75 9C 000008F3: E0 3E 000008F4: 4D 39 000008F5: 83 8E 000008F6: 6E 54 000008F7: 1E 26 000008F8: 02 01 - Ian
哦,这比我预期的要多。为了查看实际发生了什么变化,在VS命令提示符(或运行vsvars32)中运行dumpbin /all /rawdata:none命令,并对两个文件进行windiff比较。第一个将是时间戳,我猜其中之一将是调试GUID,但想不出第三个是什么。 - Rup

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