我在VS2005中创建了一个简单的“Hello World”应用程序。这是一个直接的控制台应用程序;它只包含以下几行:
Console.WriteLine("Hello World");
Console.ReadLine();
当我尝试重建相同的控制台应用程序而不执行任何更改(只需按下重建按钮)时,我得到一个微妙的不同可执行文件。 (我从第一个和第二个生成的可执行文件中生成了一个SHA-1哈希,它是不同的!)
为什么在没有代码更改时会有所不同?实际改变了什么?我使用十六进制编辑器进行比较,只看到几个不同的字节。
我想我的最终问题是,我怎么知道“集会”是否确实改变了? (当然不看文件版本,文件大小等)
修改
到目前为止,我们已经确定差异在于PE头(时间戳和一些调试数据)。在重新发明轮子之前,是否存在忽略PE头的“装配比较”工具?
谢谢, 伊恩
答案 0 :(得分:6)
差异将是
(根据您发布的其他输出,可能还有更多内容?)要查看这些内容,请在VS命令提示符下的两个程序集上运行dumpbin /all /rawdata:none
。
要正确地执行此操作,您必须编写一个理解这一点并忽略这些字节的比较工具 - 或者获取可执行文件的副本,清除时间戳和GUID,然后比较这些版本。或者,在紧要关头,您可以使用类似fc /b
的内容作为controlfreak建议并假设如果有< 20个字节不同(4个用于时间戳,16个用于GUID)然后它可能是相同的。
你可能会使用清除时间戳的程序集 - AFAIK它只用于缓存其他DLL中的导出符号偏移量,如果你把它挂起来 - 但它可能更安全。如果你真的需要二进制相同的程序集,我建议你改变你的进程,这样你就不会进行清理构建,除非你真的需要它。
答案 1 :(得分:2)
从Visual Studio命令提示符,您可以进行更详细的比较:
您可以使用dumpbin
的输出比较PE标头:
dumpbin /HEADERS assembly.dll
或者您可以使用ildasm
比较PE标头和装配中嵌入的IL代码:
ildasm /ALL /TEXT assembly1.dll > dump1.txt
ildasm /ALL /TEXT assembly2.dll > dump2.txt
fc dump1.txt dump2.txt
/ALL
选项将转储DOS和PE头,CLR头,程序集元数据和反汇编的IL。但是,它不包含嵌入的资源。如果您的assmembly包含嵌入资源,则可以使用/OUT
选项。这将为每个嵌入式资源创建一个单独的文件,您可以使用自己喜欢的diff工具进行比较,例如:的WinMerge:
ildasm /ALL /TEXT /OUT:folder1\dump.txt folder1\assembly.dll
ildasm /ALL /TEXT /OUT:folder2\dump.txt folder2\assembly.dll
答案 2 :(得分:0)
在命令行上 fc / b< oldfile> < newfile>