Определите, были ли сборки .NET созданы из одного источника - PullRequest
29 голосов
/ 31 мая 2010

Кто-нибудь знает способ сравнения двух сборок .NET, чтобы определить, были ли они собраны из "одинаковых" исходных файлов?

Я знаю, что есть несколько разностных утилит, таких как плагин для Reflector, но я не заинтересован в просмотре различий в графическом интерфейсе, я просто хочу автоматизированный способ сравнить набор двоичных файлов, чтобы увидеть, были ли они построен из тех же (или эквивалентных) исходных файлов. Я понимаю, что несколько разных исходных файлов могут создавать один и тот же IL, и понимаю, что процесс будет чувствителен только к различиям в IL, а не к исходному.

Основным препятствием для простого сравнения потоков байтов для двух сборок является то, что .NET включает в себя поле под названием «MVID» (идентификатор версии модуля) сборки. Похоже, что для каждой компиляции это значение имеет разные значения, поэтому если вы создадите один и тот же код дважды, сборка будет отличаться.

Смежный вопрос: кто-нибудь знает, как заставить MVID быть одинаковым для каждой компиляции? Это избавило бы нас от необходимости иметь процесс сравнения, который нечувствителен к различиям в значении MVID. Было бы предпочтительнее использовать согласованный MVID, поскольку это означает, что можно использовать стандартные контрольные суммы.

Основанием для этого является то, что сторонняя компания несет ответственность за независимую проверку и подписание наших выпусков до того, как нам разрешат выпустить в производство. Это включает в себя просмотр исходного кода. Они хотят независимо подтвердить, что предоставляемый им исходный код соответствует двоичным файлам, которые мы ранее создали, протестировали и в настоящее время планируем развернуть. Мы ищем процесс, который позволит им независимо собрать систему из источника, который мы им поставляем, и сравнить контрольные суммы с контрольными суммами для двоичных файлов, которые мы тестировали.

КСТАТИ. Обратите внимание, что мы используем непрерывную интеграцию, автоматические сборки, контроль исходного кода и т. Д. Проблема не связана с отсутствием внутреннего контроля над тем, какие исходные файлы вошли в данную сборку. Проблема заключается в том, что третья сторона несет ответственность за проверку того, что источник, который мы им предоставляем, производит те же двоичные файлы, которые мы протестировали и планируем использовать в Production. Они не должны доверять ни одной из наших внутренних систем или элементов управления, включая сервер сборки или систему контроля исходного кода. Все, что их волнует, - это получить исходный код, связанный со сборкой, выполнить сборку самостоятельно и убедиться, что выходные данные соответствуют тому, что мы говорим о развертывании.

Скорость выполнения решения сравнения не особенно важна.

спасибо

Ответы [ 7 ]

10 голосов
/ 07 июля 2010

Не так уж сложно использовать инструменты командной строки для фильтрации MVID и отметок даты и времени из текстового представления IL. Предположим, file1.exe и file2.exe созданы из одних и тех же источников:

c: \ temp> ildasm / all / text file1.exe | найти / v "Отметка даты и времени:" | find / v "MVID"> file1.txt

c: \ temp> ildasm / all / text file2.exe | найти / v "Отметка даты и времени:" | find / v "MVID"> file2.txt

c: \ temp> fc file1.txt file2.txt

Сравнение файлов file1.txt и FILE2.TXT

FC: различий не обнаружено

8 голосов
/ 22 ноября 2011

При сравнении библиотек классов с ILDasm v4.0.319.1 создается впечатление, что база изображений не инициализирована. Чтобы избежать несоответствий, используйте пересмотренное решение:

ildasm /all /text assembly.dll
| find /v "// Time-date stamp:"
| find /v "// MVID:"
| find /v "// Checksum:"
| find /v "// Image base:"
> assembly.dasm

Точка входа (основа изображения) на самом деле представляет интересную информацию для исполняемых сборок и должна быть тщательно проверена. Внедрение новой базы изображений - это обычный способ заставить программу делать что-то совсем другое. В моем случае я пытаюсь проверить согласованность многопоточных сборок, поэтому можно безопасно пропустить точку входа.

Замечание по производительности: я взял 8 МБ DLL, созданную для AnyCPU, и запустил ILDasm. Получившийся файл имел размер 251 МБ и занял несколько минут. Примерно 32x размер был произведен.

8 голосов
/ 19 мая 2011

Я использовал решение Джерри Керри на сборках .Net 4 и обнаружил, что теперь есть третий элемент, который будет меняться в каждой сборке: контрольная сумма. Не удивительно ли найти контрольную сумму внутри сборки? Я думаю, что добавление контрольной суммы файла внутри этого файла изменит контрольную сумму ...

В любом случае, измененная команда:

ildasm /all /text "assembly.dll"
| find /v "// Time-date stamp:"
| find /v "// MVID:"
| find /v "// Checksum:"
> assembly.dasm

Обратите внимание, что я также немного изменил строки поиска, добавив косую черту, чтобы избежать непреднамеренных совпадений. Строки этой команды должны быть запущены вместе в одной строке, разделены для удобства чтения. Имена файлов будут заключаться в двойные кавычки, если они содержат пробелы.

3 голосов
/ 19 июня 2011

Вы можете использовать MonoCecil и внести в него небольшие изменения, чтобы решить проблему. Я сделал это, вы можете прочитать, как здесь: http://groups.google.com/group/mono-cecil/browse_thread/thread/6ab42df05daa3a/49e8b3b279850f13#49e8b3b279850f13

С уважением, Флориан

3 голосов
/ 31 мая 2010

Есть несколько способов сделать это в зависимости от объема работы, которую вы готовы выполнять, а также важности производительности и / или точности. Один из способов, как указал Эрик Дж., Состоит в том, чтобы сравнивать сборки в двоичном формате, исключая части, которые меняются при каждой компиляции. Это простое и быстрое решение, но оно может дать вам много ложных негативов. Одним из лучших способов является углубление с помощью отражения. Если производительность критична, вы можете начать со сравнения типов и, если они совпадают, перейти к определениям элементов. После проверки типов и определений членов, и если все равно этому пункту, вы можете пойти дальше, изучив фактический IL каждого метода, получив его методом GetILAsByteArray. Опять же, вы найдете различия, даже если все будет одинаково, но скомпилировано с немного другими флагами или другой версией компилятора. Я бы сказал, что лучшим решением является использование инструментов непрерывной интеграции, которые помечают сборку номером набора изменений вашего исходного управления (вы используете один, верно?).

Статья по теме

1 голос
/ 13 марта 2014

Вы можете использовать Refiffor Diff AddIn здесь .

0 голосов
/ 18 ноября 2010

Другое решение для рассмотрения:

Информация об исходном коде сохраняется при компиляции двоичных файлов в режиме отладки. Затем вы можете проверить, соответствует ли pdb exe и соответствуют ли строки pdb исходному коду.

...