Сборки .NET, установка
приложений и COM Interop
В завершение мы
решили остановиться на проблемах
установки и размещения программ, а
также на использовании готовых
программ, использующих модель 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 и ХР — и
то если об этом специально
позаботится разработчик программы.
Давайте
посмотрим, что происходит на уровне
реестра при регистрации
компонентов СОМ.
- Разработчик
создает для компонента
глобально-уникальный
идентификатор (GUID).
- Разработчик
создает для компонента
программный идентификатор (ProgID).
- Утилита
регистрации связывает ProgID
компонента с GUID, создавая
соответствующую запись в
реестре.
- Утилита
регистрации заносит полный
путь к двоичному файлу
компонента в реестр и
связывает его с GUID компонента.
- Утилита
регистрации также может
сохранить в реестре
дополнительные сведения о
компоненте — например, тип
потоковой модели.
При попытке
использования компонента
происходит следующее:
- Разработчик
приложения создает экземпляр
компонента, используя ProgID.
- СОМ
ищет в реестре GUID компонента.
- СОМ
находит двоичный файл
компонента.
- СОМ
создает экземпляр компонента.
Несмотря на
большое количество выполняемых
операций, главные проблемы
возникают при копировании в
систему нового файла с компонентом,
не сопровождающимся обновлением
реестра, и при смене GUID. Приложение,
которое раньше благополучно
работало, работать перестает. Это
связано с тем, что в механизме
установки СОМ не предусмотрено
нормальных средств для контроля
версии компонентов.
Как было
сказано в начале этой главы,
процесс установки в .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, а
также указывать другие сведения,
необходимые для загрузки сборки.