Сборки .NET, установка приложений и COM Interop

  • Принципы работы СОМ
  • Сборки .NET
  • Манифест
  • Исследование манифеста
  • Общие сборки и GAC
  • Включение и удаление сборок из GAC
  • Сильные имена и совместное использование сборок
  • Построение ключей
  • Сертификация сборки
  • COM Interop и вызовы функций DLL
  • Вызовы функций DLL
  • В завершение мы решили остановиться на проблемах установки и размещения программ, а также на использовании готовых программ, использующих модель COM (Component Object Model). Вообще-то на эту тему можно написать целую книгу, но мы надеемся, что это короткое вступление поможет вам перейти к самостоятельному изучению этой темы.

    Установка большинства приложений .NET сводится к простому копированию каталога, содержащего необходимые файлы, на любой компьютер с установленной исполнительной средой .NET. Программа запускается двойным щелчком на имени ЕХЕ-файла в окне Проводника (Windows Explorer).

    Выбирая значок Setup and Deployment Project в диалоговом окне New Project, вы получите доступ к весьма нетривиальным возможностям установки. Мастер Setup Wizard чрезвычайно прост в использовании, но для большинства стандартных ситуаций его возможностей оказывается вполне достаточно.

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

    Во многих устанавливаемых приложениях хотя бы часть работы выполняется традиционными объектами СОМ, поэтому в этой главе будут кратко затронуты вопросы использования объектов СОМ в .NET [ И наоборот — объекты .NET могут использоваться в СОМ, однако эта возможность выглядит несколько экзотически. ]. А поскольку одной из целей разработки .NET было исправление недостатков СОМ, мы начнем с краткого обзора СОМ и основных проблем, связанных с этой технологией.

     

    Принципы работы СОМ

    Технология СОМ упрощает создание программ, сохраняющих совместимость в разных версиях платформы Windows и более или менее независимых от языка программирования. Компоненты СОМ могут создаваться на разных языках, включая классический С (вариант для мазохистов), C++, Delphi, VB5 и 6. Технология СОМ с большим успехом применялась для создания объектов, предназначенных для решения специализированных задач, таких как элементы VB OCX.

    Технология СОМ была задумана как механизм, при помощи которого программные компоненты получают информацию о возможностях других компонентов и обращаются к ним с запросами, не беспокоясь о подробностях внутренней реализации [ Существуют и другие технологии, ориентированные на повторное использование программного кода (например, CORBA), но пока наибольшего успеха добилась именно модель СОМ. ]. Для этого был выработан стандартный протокол получения информации об интерфейсах, поддерживаемых другими компонентами, наряду со стандартизацией средств для обращения к конкретной реализации интерфейса в экземплярах.

    Тем не менее у СОМ были свои недостатки. Во-первых, реализация СОМ для Windows требовала, чтобы в системном реестре хранилась вся информация обо всех компонентах в системе. Пользователю приходилось регистрировать компоненты при установке программ и стирать соответствующую информацию при удалении программ. При попытке удаления программ возникала опасность того, что изменения, внесенные в реестр, повлияют на работу других программ. Стоило серьезно повредить реестр, и система вообще переставала работать. Более того, установка новой версии компонента нередко нарушала работу программ, рассчитанных на более раннюю версию компонента.

    В Windows 98 была впервые представлена концепция параллельного выполнения (side-by-side execution); это означало, что приложение могло использовать локальный экземпляр компонента СОМ, находящийся в каталоге приложения, вместо экземпляра, зарегистрированного в системе. Справедливости ради следует сказать, что параллельное выполнение так и не решило проблемы с «кошмаром DLL», вдобавок оно работает только в Windows 98, 2000 и ХР — и то если об этом специально позаботится разработчик программы.

    Давайте посмотрим, что происходит на уровне реестра при регистрации компонентов СОМ.

    1. Разработчик создает для компонента глобально-уникальный идентификатор (GUID).
    2. Разработчик создает для компонента программный идентификатор (ProgID).
    3. Утилита регистрации связывает ProgID компонента с GUID, создавая соответствующую запись в реестре.
    4. Утилита регистрации заносит полный путь к двоичному файлу компонента в реестр и связывает его с GUID компонента.
    5. Утилита регистрации также может сохранить в реестре дополнительные сведения о компоненте — например, тип потоковой модели.

    При попытке использования компонента происходит следующее:

    1. Разработчик приложения создает экземпляр компонента, используя ProgID.
    2. СОМ ищет в реестре GUID компонента.
    3. СОМ находит двоичный файл компонента.
    4. СОМ создает экземпляр компонента.

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

     

    Сборки.NET

    Как было сказано в начале этой главы, процесс установки в .NET часто сводится к простому копированию файлов, после чего программа готова к немедленному запуску. Если удалить скопированные файлы, то работать перестает только эта конкретная программа. В этом процессе не используется реестр и не учитываются зависимости между компонентами. Чтобы эта схема нормально работала, в .NET используется концепция сборки.

    С технической точки зрения сборка (assembly) в .NET представляет собой минимальную устанавливаемую единицу программного кода. Сборка оформляется в виде автономного ЕХЕ-файла или в виде библиотеки DLL, на которую можно ссылаться из других приложений. Однако сборка содержит нечто большее, чем обычный IL-код, компилируемый и выполняемый исполнительной средой .NET. Как минимум, сборка состоит из одного или нескольких модулей и классов, откомпилированных в IL-код, и метаданных (данных, описывающих данные [ Префикс «мета» для подобных абстракций второго порядка позаимствован из метаматематики — области математики, посвященной описанию самих математических объектов. ]), которые описывают сборку и функциональность входящих в нее классов. Метаданные являются частью сборки, поэтому в документации сборки названы самодокументируемыми. Во многих ситуациях сборка состоит из одного файла, но встречаются и многофайловые сборки. Например, в сборку могут входить ресурсные файлы, графические изображения и даже дополнительные EXE/DLL-файлы. В любом случае сборка является минимальным объектом .NET, для которого производится контроль версии или задаются привилегии.

    В большинстве случаев создаются однофайловые сборки, состоящие из одного ЕХЕ-или DLL-файла.

    Сборки бывают закрытыми (private) и общими (shared). Закрытые сборки всегда находятся в каталоге приложения или в одном из его подкаталогов. Общие сборки хранятся в глобальном кэше сборок (GAC, global assembly cache). Начнем с закрытых сборок, поскольку именно они используются по умолчанию для решений, построенных в VS .NET IDE. С общими сборками дело обстоит сложнее, и мы займемся ими позже.

    Обычно у закрытых сборок не бывает проблем с несовместимостью версий, однако они требуют дополнительных затрат дискового пространства, если в системе приходится хранить несколько копий одного файла в разных каталогах [ В наше время дисковое пространство обходится так дешево, что эти затраты с избытком компенсируются удобствами, связанными с использованием закрытых сборок. ]. При создании ссылок на сборку командой Project > Add Reference по умолчанию в каталоге приложения создается новый экземпляр закрытой сборки. Мы рекомендуем по возможности ограничиваться использованием закрытых сборок.

    Для управления сборками используются конфигурационные файлы в формате XML. Конфигурационный файл должен находиться в одном каталоге с файлом, содержащим точку входа в сборку. С его помощью можно управлять привилегиями, назначать каталоги для поиска зависимых DLL, а также указывать другие сведения, необходимые для загрузки сборки.