Определенная корпорацией Microsoft для использования в последних версиях Windows , сборка в Common Language Infrastructure (CLI) представляет собой скомпилированную библиотеку кода, используемую для развертывания, управления версиями и безопасности. Существует два типа: сборки процессов ( EXE ) и сборки библиотек ( DLL ). Сборка процессов представляет собой процесс, который будет использовать классы, определенные в сборках библиотек. Сборки CLI содержат код на языке CIL , который обычно генерируется из языка CLI , а затем компилируется в машинный язык во время выполнения компилятором just-in-time . В реализации .NET Framework этот компилятор является частью Common Language Runtime (CLR).
Сборка может состоять из одного или нескольких файлов. Файлы кода называются модулями. Сборка может содержать более одного модуля кода. И поскольку для создания модулей кода можно использовать разные языки , технически возможно использовать несколько разных языков для создания сборки. Однако Visual Studio не поддерживает использование разных языков в одной сборке.
Название сборки состоит из четырех частей
Токен открытого ключа используется для того, чтобы сделать имя сборки уникальным. Таким образом, две сборки со строгими именами могут иметь одинаковое имя файла PE, и все же CLI распознает их как разные сборки. Файловая система Windows ( FAT32 и NTFS ) распознает только имя файла PE, поэтому две сборки с одинаковым именем файла PE (но разной культурой, версией или токеном открытого ключа) не могут существовать в одной папке Windows. Чтобы решить эту проблему, CLI вводит GAC ( глобальный кэш сборок ), который рассматривается как одна папка во время выполнения, но фактически реализован с использованием вложенных папок файловой системы.
Чтобы предотвратить атаки спуфинга , когда взломщик пытается выдать сборку за что-то другое, сборка подписывается закрытым ключом. Разработчик предполагаемой сборки хранит закрытый ключ в секрете, поэтому взломщик не может получить к нему доступ или просто угадать его. Таким образом, взломщик не может заставить свою сборку выдавать себя за что-то другое, не имея возможности правильно подписать ее после изменения. Подписание сборки включает в себя получение хеша важных частей сборки и последующее шифрование хеша закрытым ключом. Подписанный хеш хранится в сборке вместе с открытым ключом. Открытый ключ расшифрует подписанный хеш. Когда CLR загружает строго именованную сборку, она сгенерирует хеш из сборки, а затем сравнит его с расшифрованным хешем. Если сравнение проходит успешно, то это означает, что открытый ключ в файле (и, следовательно, токен открытого ключа) связан с закрытым ключом, используемым для подписи сборки. Это будет означать, что открытый ключ в сборке является открытым ключом издателя сборки, и, следовательно, атака спуфинга предотвращается.
Сборки CLI могут иметь информацию о версии, что позволяет им устранить большинство конфликтов между приложениями, вызванных общими сборками. [2] Однако это не устраняет все возможные конфликты версий между сборками. [3]
Безопасность доступа к коду CLI основана на сборках и доказательствах . Доказательства могут быть любыми, выведенными из сборки, но обычно они создаются из источника сборки — была ли сборка загружена из Интернета, интрасети или установлена на локальной машине (если сборка загружена с другой машины, она будет сохранена в изолированном месте в GAC и, следовательно, не будет считаться установленной локально). Разрешения применяются ко всем сборкам, и сборка может указать минимальные требуемые ей разрешения с помощью настраиваемых атрибутов (см. метаданные CLI ). Когда сборка загружена, CLR будет использовать доказательства для сборки, чтобы создать набор разрешений из одного или нескольких разрешений доступа к коду. Затем CLR проверит, содержит ли этот набор разрешений требуемые разрешения, указанные сборкой.
Код CLI может выполнить требование безопасности доступа к коду. Это означает, что код выполнит некоторое привилегированное действие только в том случае, если все сборки всех методов в стеке вызовов имеют указанное разрешение. Если у одной сборки нет разрешения, выдается исключение безопасности.
Код CLI также может выполнять Linked Demand для получения разрешения из стека вызовов. В этом случае CLR будет искать только один метод в стеке вызовов в позиции TOP для указанного разрешения. Здесь проход по стеку привязан к одному методу в стеке вызовов, с помощью которого CLR предполагает, что все остальные методы в CALL STACK имеют указанное разрешение. Сборка представляет собой комбинацию METADATA и файла MSIL.
В общем, сборки должны содержать культурно-нейтральные ресурсы. Если вы хотите локализовать свою сборку (например, использовать разные строки для разных локалей), вам следует использовать сателлитные сборки — специальные сборки, содержащие только ресурсы. Как следует из названия, сателлит связан со сборкой, называемой основной сборкой. Эта сборка (например, lib.dll) будет содержать нейтральные ресурсы (которые Microsoft называет международными английскими , но подразумевает, что это американский английский). Каждый сателлит имеет имя связанной библиотеки, дополненное .resources (например, lib.resources.dll). Сателлиту дается ненейтральное культурное имя, но поскольку это игнорируется существующими файловыми системами Windows (FAT32 и NTFS), это будет означать, что в одной папке может быть несколько файлов с одинаковым именем PE. Поскольку это невозможно, сателлиты должны храниться в подпапках в папке приложения. Например, сателлит с ресурсами на британском английском будет иметь имя CLI «lib.resources Version=0.0.0.0 Culture=en-GB PublicKeyToken=null», имя PE-файла lib.resources.dll и будет храниться в подпапке с именем en-GB.
Спутники загружаются классом CLI, который называется System.Resources.ResourceManager
. Разработчик должен предоставить имя ресурса и информацию об основной сборке (с нейтральными ресурсами). Класс ResourceManager будет считывать локаль машины и использовать эту информацию и имя основной сборки, чтобы получить имя спутника и имя подпапки, которая его содержит. ResourceManager
затем можно загрузить спутник и получить локализованный ресурс.
Ссылаться на библиотеку исполняемого кода можно с помощью флага /reference компилятора C#.
Общие сборки должны давать строгое имя для уникальной идентификации сборки, которая может быть общей для приложений. Строгое именование состоит из токена открытого ключа, культуры, версии и имени файла PE. Если сборка, вероятно, будет использоваться для целей разработки, которая является общей сборкой, процедура строгого именования содержит только генерацию открытого ключа. Закрытый ключ не генерируется в это время. Он генерируется только при развертывании сборки.
Сборка построена с помощью кода CIL, который является промежуточным языком. Фреймворк внутренне преобразует CIL ( байт-код ) в собственный код сборки . Если у нас есть программа, которая печатает "Hello World", эквивалентный код CIL для метода будет следующим:
. method private hidebysig static void Main ( string [] args ) cil managed { . entrypoint . custom instance void [ mscorlib ] System . STAThreadAttribute ::. ctor () = ( 01 00 00 00 ) // Размер кода 11 (0xb) . maxstack 1 IL_0000 : ldstr "Hello World" IL_0005 : call void [ mscorlib ] System . Console :: WriteLine ( string ) IL_000a : ret } // конец метода Class1::Main
Код CIL загружает строку в стек, затем вызывает функцию WriteLine и возвращает управление.