7

我在 VS2005 中创建了一个简单的“Hello World”应用程序。这是一个直接的控制台应用程序;它只包含以下几行:

Console.WriteLine("Hello World");
Console.ReadLine();

当我尝试重建同一个控制台应用程序而不执行任何更改时(只需按下重建按钮),我得到一个略有不同的可执行文件。(我从第一个和第二个生成的可执行文件中生成了一个 SHA-1 哈希,它是不同的!)

为什么没有代码更改时会有所不同?究竟发生了什么变化?我使用十六进制编辑器进行比较,只看到几个不同的字节。

我想我的最终问题是,我怎么知道“组装”是否真的发生了变化?(当然不看文件版本、文件大小等)

编辑

到目前为止,我们已经确定区别在于 PE 标头(时间戳和一些调试数据)。在我重新发明轮子之前,是否有忽略 PE 标头的“程序集比较”工具?

谢谢,伊恩

4

3 回答 3

6

差异将是

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

(也许还有更多,根据您发布的其他输出?)要查看这些,请dumpbin /all /rawdata:none在 VS 命令提示符下在两个程序集上运行。

要正确执行此操作,您必须编写一个比较工具来理解这一点并忽略这些字节 - 或者复制可执行文件,清除时间戳和 GUID,然后比较这些版本。或者,在紧要关头,您可以使用fc /bcontrolfreak 建议的内容,并假设如果有 < 20 个字节不同(时间戳为 4,GUID 为 16),那么它可能是相同的。

您很可能会使用清除时间戳的程序集 - AFAIK,如果您将其连接起来,它仅用于在其他 DLL 中缓存导出的符号偏移量 - 但保持原样可能更安全。如果您确实需要二进制相同的程序集,我建议您更改您的流程,这样除非您真的需要它,否则您永远不会清理构建。

于 2010-07-23T08:36:17.613 回答
2

在 Visual Studio 命令提示符下,您可以进行更详细的比较:

  • 您可以使用以下输出来比较 PE 标头dumpbin

    dumpbin /HEADERS assembly.dll
    
  • 或者您可以使用以下命令比较 PE 头文件和嵌入在程序集中的 IL 代码ildasm

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

    /ALL选项将转储 DOS 和 PE 标头、CLR 标头、程序集元数据和反汇编的 IL。但是,它不包含嵌入式资源。如果您的程序集包含嵌入式资源,您可以使用该/OUT选项。这将为每个嵌入式资源创建一个单独的文件,您可以使用您喜欢的差异工具进行比较,例如 WinMerge:

    ildasm /ALL /TEXT /OUT:folder1\dump.txt folder1\assembly.dll
    ildasm /ALL /TEXT /OUT:folder2\dump.txt folder2\assembly.dll
    
于 2010-07-23T08:46:12.040 回答
0

在命令行 fc /b <旧文件> <新文件>

于 2010-07-23T08:28:16.880 回答