Почему код IL упакован в исполняемый файл в приложении C #? - PullRequest
20 голосов
/ 30 марта 2011

Я пытался восстановить exe-файл, выполняя обход ILDASM и затем ILASM в исполняемом файле C #. Как я понимаю, файл .il, сгенерированный ILDASM, достаточен для генерации .exe обратно.

Мне любопытно, почему .NET Framework предназначен для использования exe-файла для развертывания вместо развертывания .il-файла для пользователей. Не может ли компилятор c # сгенерировать файл .il, а JIT-компилятор напрямую использует файл .il в качестве входных данных? Это просто потому, что для запуска загрузчика операционной системе требуется расширение .exe, или это из-за размера файла или из соображений производительности?

PS: Вопрос не имеет практического значения. Я задаю этот вопрос, чтобы прояснить мои концепции, поскольку я уверен, что мне не хватает много.

Ответы [ 4 ]

16 голосов
/ 30 марта 2011

Не имеет никакого смысла добавлять другие типы расширений только для обслуживания .NET.

.NET исполняемые файлы представляют собой PE-файлы, и они предоставляют минимальный объем собственного кода для начальной загрузки правильной версии CLR, извлечения IL-файла в память и передачи в CLR.

Windows изначально знает, что делать с PE-файлами, и с помощью механизма косвенности, встроенного в EXE. Windows также не нужно знать о .NET.

С файлом .il вам необходимо зарегистрировать расширение в Windows, а затем убедиться, что загружена правильная версия CLR - насколько я знаю, вы можете связать расширение только с одним исполняемым файлом.

Для поддержки нескольких версий CLR вам потребуется какой-то посредник, который затем проверяет ваш файл .il, чтобы определить, какой CLR загружать .... и после этого все становится запутанным и хрупким.

Упаковка всего этого в PE решает эти проблемы аккуратно и элегантно.

Несмотря на то, что это более старая статья, принципы остаются неизменными в современных платформах .NET:

Углубленный взгляд на формат исполняемых файлов Win32, часть 2

В разделе «Заголовок .NET» объясняется, как это работает:

Исполняемые файлы, созданные для Microsoft .NET среды являются первыми и прежде всего PE файлы. Однако в большинстве дел нормальный код и данные в .NET файл минимален. Основная цель исполняемого файла .NET, чтобы получить .NET-специфичная информация, такая как метаданные и промежуточный язык (IL) в память. Кроме того, .NET исполняемые ссылки на MSCOREE.DLL. Эта DLL является отправной точкой для .NET процесс. Когда исполняемый файл .NET загружает, его точка входа обычно крошечная заглушка кода. Эта заглушка просто переходит к экспортируемой функции в MSCOREE.DLL (_CorExeMain или _CorDllMain). Оттуда MSCOREE берет на себя ответственность и начинает использовать метаданные и IL из исполняемого файла файл. Эта установка похожа на способ приложения в Visual Basic (до .NET) использовал MSVBVM60.DLL. Отправная точка для .NET информация является Структура IMAGE_COR20_HEADER, в настоящее время определяется в CorHDR.H из .NET Framework SDK и более поздние версии версии WINNT.H. IMAGE_COR20_HEADER указывает на IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR запись в DataDirectory. Рисунок 10 показывает поля IMAGE_COR20_HEADER. Формат метаданные, метод IL и другие вещи на который указывает IMAGE_COR20_HEADER будет описано в следующем статья.

4 голосов
/ 30 марта 2011

.exe файлы меньше.
Они также соответствуют существующему стандартному формату PE, что упрощает интеграцию с Windows.

Java необходимо зарегистрировать расширение .jar и связать его с java.exe в пути одиночной JRE.

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

Кроме того, анализ выполняется медленно; .il файлы будут выполняться медленнее, потому что среда выполнения должна будет проанализировать IL.

2 голосов
/ 30 марта 2011

Ранние версии Windows не имели поддержки уровня .net для операционной системы. Это приводит к некоторым альтернативам:

  1. EXE-файл, который загружает .net CLR, а затем использует его для запуска IL. Недостатком этого является то, что вы не можете различить exe-файл, содержащий .net IL и нативный exe-файл. Это актуально, если вы хотите запустить его с ограниченными привилегиями .net.
    Тот факт, что программа неотличима от нативной программы, может привести к более высокому признанию.
    Это также позволяет заменить собственную программу на .net-программу без необходимости изменять весь код, который ее вызывает.
  2. Новый формат файла, содержащий двоичный IL. Подобно jar-файлам java. При двойном щелчке они открываются соответствующей программой. Что-то вроде "rundotnet.exe myprogram.net".
    Это приводит к проблемам с программами, которые предполагают однозначное сопоставление между исполняемыми файлами программы и логическими программами. Это включает в себя брандмауэры и функцию группировки панели задач. В диспетчере задач вы не видите, что соответствует нескольким "rundotnet.exe", которые вы видите, ...
    И сборки, которые смешивают собственный и .net-код, также невозможны с этим решением.
    Большим преимуществом этого является то, что программный код может быть проверен средой выполнения .net перед выполнением.
  3. PE-файл с новым расширением. Это мой любимый. В старых версиях Windows вы можете просто добавить запись в реестр, чтобы запустить ее как обычную программу, а в новых версиях вы можете дать ей особый режим. Это позволяет избежать проблем как 2, так и 3.

Благодаря встроенной поддержке ОС можно было бы избежать большинства проблем, связанных с отдельным форматом файла. Выбор 1) более 2) понятен, но я не знаю, почему они не выбрали 3. Я предполагаю, что им понравилось иметь все (современные) исполняемые файлы с одинаковым расширением файла.

0 голосов
/ 30 марта 2011

.Net runtime / JIT использует представление байтового кода IL. Это похоже на сборку, компилируемую в машинный код. Это требует меньшего воздействия и легче проверить целостность двоичных данных, чем если бы вы пытались поддерживать IL как «исполняемый» код. Это также увеличит размер файлов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...