Я создал простое "Привет Мировое" приложение в VS2005. Это - простое консольное приложение; это только содержит следующие строки:
Console.WriteLine("Hello World");
Console.ReadLine();
Когда я пытался восстановить то же консольное приложение, не выполняя изменений (просто нажимают восстановить кнопку), я получаю тонко другой исполняемый файл. (Я генерировал хеш SHA-1 и от 1-го и от 2-го сгенерированного исполняемого файла, и это отличается!)
Почему это отличается, когда нет никаких изменений кода? Что на самом деле изменилось? Я использовал Hex-редактор для сравнения и только видел пару различных байтов.
Я предполагаю, что мой окончательный вопрос, как я могу знать, изменялся ли "блок" действительно? (Конечно, не смотря на Версии файла, размер файла, и т.д.)
Править
До сих пор мы установили, что различие заключается в заголовке PE (метка времени и некоторые отладочные данные). Прежде чем я изобрету велосипед, существует ли "инструмент" сравнения блока, который игнорирует заголовок PE?
Спасибо, Ian
Различия будут заключаться в
(и, возможно, что-то еще, согласно другим данным, которые вы выложили?) Чтобы увидеть их, запустите dumpbin /all /rawdata:none
на обеих сборках в командной строке VS.
Чтобы сделать это правильно, вам придется написать инструмент сравнения, который понимает это и игнорирует эти байты - или сделать копии исполняемых файлов, очистить метку времени и GUID, а затем сравнить эти версии. Или, в крайнем случае, можно использовать что-то вроде fc /b
, как предлагает controlfreak, и считать, что если разница в байтах < 20 (4 для временной метки, 16 для GUID), то это, вероятно, одно и то же.
Вы вполне можете обойтись использованием сборки с очищенной меткой времени - AFAIK она используется только для кэширования смещений экспортируемых символов в других DLL, если вы подключите их - но, вероятно, безопаснее оставить все как есть. Если вам действительно нужны двоично-идентичные сборки, я предлагаю изменить ваши процессы так, чтобы вы никогда не выполняли clean-build, если только вам это действительно не нужно.
Из командной строки 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