Сборки и развертывание


Именно благодаря операции развертывания тяжелая работа программиста становится доступной пользователю. Сборки .NET делают развертывание намного более простым и намного более надежным, чем традиционное развертывание Windows. Частное развертывание сборки столь же просто, как копирование компонента сборки в тот же самый каталог, в котором расположена клиентская программа. А общедоступное развертывание сборки регистрирует компонент с уникальным именем (известным как строгое имя) в глобальном кэше сборок, благодаря чему сборка становится доступной для общего использования.
Эта глава начинается с обсуждения понятий сборки, которая является основной единицей развертывания при частном развертывании сборки в .NET. Затем описано и общедоступное развертывание сборки. Управление версиями и цифровое подписание сборок обсуждаются в контексте общедоступного развертывания. После этого на примере программы Hotel (Гостиница) демонстрируется инсталляция и приемы развертывания сборок. Наконец, представлены развертывание Visual Studio.NET и мастера установки. По ходу обсуждения мы иллюстрируем множество полезных инструментальных средств, которые являются частью комплекса инструментальных средств разработки программ .NET Framework SDK.

Сборки


Сборки положены в основу технологии компонентов .NET. Сборка — основная единица развертывания и управления разрешениями защиты, версиями, а также повторным использованием двоичного кода. Сборка содержит двоичный выполнимый код, составленный из команд управляемого промежуточного языка 1L (Intermediate Language), a также метаданных, которые полностью описывают содержимое сборки. Сборки могут также содержать данные ресурса и быть упакованы в виде динамически подключаемой библиотеки (DLL) или ЕХЕ-файлов. Сборка может быть составлена из одного или нескольких физических файлов на диске, но это — все равно одна логическая единица развертывания. Сборки, как говорят, описывают себя сами, так как они содержат в метаданных информацию о себе, и поэтому для их установки не требуется никакой внешней информации, например, в системном реестре. Это делает .NET-компоненты намного более простыми и менее подверженными ошибкам при установке и деинсталляции, чем традиционные компоненты, построенные на основе модели компонентных объектов Microsoft (СОМ), которые имели обширные требования к информации в системном реестре. Мало того, что сборки описывают себя сами, они также содержат и хэш-код, представляющий двоичное содержимое сборки. Этот хэш-код может использоваться для того, чтобы подтвердить подлинность и обнаружить тайные изменения или искажение сборок с цифровой подписью.
Прежде чем развернуть сборку в глобальном кэше сборок, ее сначала необходимо подписать в цифровой форме. Сборка с цифровой подписью имеет криптографически сгенерированную информацию, которую общеязыковая среда выполнения CLR может использовать для проверки, чтобы выполнить важные правила зависимости при размещении и загрузке сборок. Простая проверка версии гарантирует, что клиентская программа правильно использует общедоступные сборки с учетом тех их версий, которые были определены при первоначальной компиляции и тестировании клиента. Благодаря этому можно на самом деле устранить жуткую проблему "ада динамически подключаемых библиотек (DLL)", где клиенты и компоненты, построенные на основе модели компонентных объектов Microsoft (COM), могли легко "рассинхронизироваться" друг с другом, если старая версия заменялась более новой, — это нарушало работу существующих клиентов. Сборка с цифровой подписью может также проверить, что никакой неправомочный человек не изменил общедоступное содержимое сборки после того, как была поставлена цифровая подпись. Такая проверка гарантирует не только то, что вы не сможете случайно использовать неправильную версию, но также, что вы не будете злонамеренно обмануты в результате использования компонента, который мог бы причинить серьезный вред.
Хотя часто имеется взаимнооднозначное соответствие между пространством имен и сборкой, сборка может содержать множественные пространства имен, причем одно пространство имен может использоваться несколькими сборками. Точно так же часто существует взаимнооднозначное соответствие между сборкой и файлом двоичного кода (т.е. динамически подключаемой библиотекой (DLL) или исполняемым файлом). Однако одна сборка может содержать несколько файлов двоичного кода. Помните, что сборка — единица развертывания, пространства имен поддерживают иерархическую систему именования, а динамически подключаемая библиотека (DLL), или исполняемый файл— единица упаковки функциональных возможностей в пределах файловой системы. Важно также понимать разницу между сборкой, которая является единицей развертывания, и приложением, которое является единицей конфигурации.
Сборка без подписи идентифицируется просто удобочитаемым названием (именем), а также номером версии. Сборка с цифровой подписью идентифицируется также по имени ее создателя, однозначно определяемому по криптографической паре (ключей). При необходимости сборка может также включать код культуры для того, чтобы поддерживать специфические для данной культуры наборы символов и форматы строк.

Содержимое сборки


Утилита lldasm.exe может использоваться для просмотра содержимого сборки, чтобы лучше понять, как работают управление версиями, цифровое подписание и развертывание. Сначала нам понадобится сборка для экспериментирования. Здесь поможет компонент SimpleComponent, созданный с помощью Visual Studio.NET. Для его создания мы в диалоге New Project (Новый проект) выбрали шаблон managed C++ Class Library (Управляемый C++ на основе Библиотеки классов). Название проекта — SimpleComponent, а в следующих исходных файлах приведена его реализация, которая только немного изменяется в зависимости от кода, сгенерированного мастером. Вспомните, что важно объявить метод AddEmUp общедоступным, чтобы он был видим для кода вне данной сборки.
//Assemblylnfо.cpp
#include "stdafx.h" // имеет #using <mscorlib.dll>
using namespace System::Reflection;
// использование пространства имен Система::Отражение;
using namespace System::Runtime::CompilerServices;
// использование пространства имен
// Система::Время выполнения::CompilerServices;
[_assembly::AssemblyTitleAttribute("")];
[_assembly: : AssemblyDescriptionAttnbute ( "" ) ] ;
[_assembly::AssemblyConfigurationAttribute("")];
[_assembly: : AssernblyCornpanyAttribute ( "") ] ;
[_assembly::AssemblyProductAttribute("")];
[_assembly::AssemblyCopyrightAttribute("")];
[_assembly::AssemblyTrademarkAttribute("") ] ;
[_assembly::AssemblyCultureAttribute("")];
[_assembly::AssemblyVersionAttribute("1.0.*")];
[_assembly::AssemblyDelaySignAttribute(false) ] ;
[_assembly::AssemblyKeуFileAttribute("")];
t_assembly::AssemblyKeyNameAttribute("")];
//SimpleComponent.cpp
#include "stdafx.h" // имеет #using <mscorlib.dll>
#include "SimpleComponent.h"
// SimpleComponent.h
using namespace System;
// использование пространства имен Система;
namespace SimpleComponent
// пространство имен SimpleComponent
{
public _gc class SomeClass
// класс сборщика мусора SomeClass
{
public: // должен быть общедоступен, чтобы сборка могла
// предоставлять его для использования
int AddEmUp(int i, int j)
{
return i+j;
}
};
}
Как только вы создали сборку компонентов .NET, содержащую вышеупомянутый код и скомпоновали ее, вы можете с помощью Ildasm.exe просмотреть ее содержимое, включая декларацию. Декларация содержит следующую информацию о сборке:
• сборка идентифицируется по имени, версии, культуре, и, при необходимости, по цифровой сигнатуре (подписи);
• список файлов, которые составляют содержимое сборки;
• список других сборок, от которых зависит данная сборка;
• список разрешений, требуемых сборкой для ее выполнения.
Все это можно увидеть с помощью утилиты Ildasm Чтобы ее запустить, выполните следующую команду Результат выполнения показан на рис. 7.1.
Ildasm SimpleComponent.dll
Чтобы увидеть декларацию сборки SimpleComponent, выполните двойной щелчок на узле MANIFEST (МАНИФЕСТ, ДЕКЛАРАЦИЯ), который виден на рис. 7.1. Информация из манифеста показана на рис. 7.2.
Декларация содержит информацию о зависимостях и содержимом сборки Видно, что декларация сборки SimpleComponent содержит, среди других, следующую внешнюю зависимость
.assembly extern mscorlib
{
.publickeytoken = (B7 7A 5C 56 19 34 EO 89 )
.hash = (09 BB ВС 09 EF 6D 9B F4 F2 CC IB 55 76 A7 02 91
22 88 EF 77 )
.ver 1:0:2411:0
}
Инструкция метаданных .assembly extern mscorlib указывает, что сборка SimpleComponent использует (и поэтому зависит от нее) стандартную сборку mccorlib.dll, необходимую для всего управляемого кода Сборка mscorlib — общедоступная сборка, которую можно найти в каталоге \WINNT\Assembly с помощью Проводника Windows (Windows Explorer) Эта зависимость появляется в метаданных SimpleComponent.dll благодаря оператору fusing <mscorlib.dll> в первоначальном исходном тексте (Stdafxh) Если бы другой оператор #using добавлялся для другой сборки, например fusing <System WinForms.dll>, то декларация содержала бы также соответствующую инструкцию зависимости .assembly extern System. WinForms
Инструкция метаданных .publickeytoken = (В7 7А 5С 56 19 34 ЕО 89 ) указывает общедоступную лексему (маркер) открытого ключа, являющуюся хэш-кодом открытого ключа, который ставится в соответствие своему секретному ключу, принадлежащему автору сборки mscorlib Эта лексема открытого ключа на самом деле не может использоваться непосредственно, чтобы подтвердить подлинность автора mscorlib Однако первоначальный открытый ключ, указанный в декларации mscorlib может использоваться для того, чтобы математически проверить, что секретный ключ на самом деле совпадает с тем, который действительно применялся при цифровом подписании сборки mscorlib Поскольку mscorlib.dll создала Microsoft, лексема открытого ключа, приведенная выше, принадлежит Microsoft Конечно, соответствующий секретный ключ — тщательно охраняемая корпоративная тайна, и, как полагает большинство экспертов в области защиты, такой секретный ключ практически очень трудно определить по открытому ключу Однако нет никакой гарантии, что некий математический гений не найдет когда-нибудь хитроумный способ делать это проще.
Как мы вскоре увидим, инструкция . publickeytoken присутствует в декларации клиентской сборки только в случае, когда сборка, на которую есть ссылка, имеет цифровую подпись (На самом деле все сборки, предназначенные для общедоступного развертывания, должны иметь цифровую подпись) Microsoft подписала в цифровой форме стандартные сборки NET, такие KaKmscorlib.dll и System.WinForms.dll принадлежащими ей секретными ключами Именно поэтому лексема открытого ключа для многих общедоступных сборок, содержащихся в каталоге \WlNNT\Assembly, имеет то же самое повторяющееся значение Создаваемые другими производителями сборки с цифровой подписью подписаны их собственными, отличными от приведенного выше, секретными ключами, и они будут иметь отличную от приведенной выше лексему открытого ключа в декларациях их клиентской сборки Позже вы научитесь создавать ваши собственные криптографические пары секретного и открытого ключа и сможете подписывать собственные сборки цифровой подписью для их развертывания через глобальный кэш сборок.

Декларация .publickeytoken


Чтобы сэкономить память, декларация .publickeytoken содержит только самые младшие 8 байтов кэш-кода открытого ключа производителя (он состоит из 128 байтов), вычисленного с помощью алгоритма SHA1. Однако, несмотря на это, она все же может использоваться для довольно надежной проверки А вот декларация .publickey содержит полный открытый ключ. Конечно, она занимает больше места, но именно поэтому злодеям труднее найти секретный ключ, который соответствует полному открытому ключу.
Важно обратить внимание, что, хотя цифровой ключ уникален, он сам по себе не может идентифицировать фактического автора конкретного модуля Однако разработчик сборки может использовать утилиту signcode, чтобы добавить цифровое свидетельство, которое может идентифицировать издателя сборки А если зарегистрировать цифровое свидетельство у Certificate Authority (Полномочного свидетеля), например у VenSign, то пользователи смогут установить надежность источника.
Инструкция метаданных .hash = (09 ВВ ВС 09 ... 77 ) обеспечивает фиксированный размер представления хэш-кода двоичного содержимого mscor lib. dll Если бы содержимое изменилось, в результате изменился бы и этот хэш-код Несмотря на то, что хэш-код имеет компактное представление, он с высокой вероятностью характеризует сборку Поэтому вычисленный на основе первоначальных данных, он может использоваться для многих целей, включая обнаружение ошибок и проверку Хэш-код для сборки mscorlib, показанной выше, с высокой вероятностью характеризует двоичные данные сборки mscorlib Это означает, что, если бы содержимое mscor I ib. dll было изменено случайно, преднамеренно, или даже злонамеренно, то, с астрономически высокой вероятностью, новый хэш-код не совпадал бы со старым, и изменение было бы обнаружено по хэш-коду Как описано далее в разделе по цифровому подписанию сборок, секретный ключ используется для того, чтобы гарантировать, что только уполномоченный человек может зашифровать хэш-код, и это используется для подтверждения (проверки) подлинности всей сборки
Инструкция метаданных .ver 1:0:2411:0 указывает версию сборки mscorlib Формат спецификации этой версии— Major .Minor :Build:Revision (Главный Младший Компоновка Пересмотр) Через какое-то время, когда будут выпущены новые версии этой сборки, существующие клиенты, которые были скомпонованы так, чтобы использовать данную версию, продолжат использовать именно данную версию, по крайней мере те версии, у которых совпадают значения главного и младшего номера версий Более новые клиентские программы, конечно, смогут обратиться к более новым версиям этой сборки, поскольку именно для них станут доступными новые версии Старые и новые версии могут быть развернуты буквально рядом посредством кэша глобальных сборок, и быть одновременно доступны старым и новым клиентским программам Обратите внимание, что версия 1:0:2411:0, появляющаяся в клиентской декларации, принадлежит текущей версии сборки mscorlib и не связана с атрибутом версии 1.0.*, указанным в исходном тексте SimpleComponent Вскоре мы более подробно рассмотрим четыре поля, которые составляют номер версии, а также управление версиями сборки
До сих пор мы сосредотачивались на зависимостях, которые определены в декларации сборки SimpleComponent Теперь давайте подробнее рассмотрим информацию в декларации, описывающую компонент SimpleComponent, содержащийся в сборке. Обратите внимание, что эта сборка не имеет цифровой подписи, и поэтому не содержит информации о ее создателе (т е , открытый ключ она в себе не содержит)
.assembly SimpleComponent
{
.hash algorithm 0x00008004
.ver 1:0:584:39032
}
Директива .assembly
Директива . assembly объявляет декларацию и определяет, какой сборке принадлежит текущий модуль. В данном примере директива . assembly определяет SimpleComponent (в качестве имени сборки. Именно это имя (вместе с номером версии и, возможно, открытым ключом), а не имя динамически подключаемой библиотеки (DLL) или (.исполняемого файла, используется во время выполнения для определения принадлежности сборки. Обратите также внимание, что, если сборка подписана, то в |директиве .assembly будет определен параметр .publickey. Директива .assembly декже указывает, добавлялись ли какие-либо пользовательские атрибуты к метаданным. Инструкция метаданных .assembly SimpleComponent указывает, что имя ысборки — SimpleComponent. Имейте в виду, что это — не имя класса компонента в рЬборке, а само имя сборки.
Алгоритмы хэширования
Алгоритм хэширования— математическая функция, которая берет первоначальные Ввходные данные произвольной длины и генерирует хэш-код, также известный как щрофиль сообщения, который представляет собой двоичный результат установленной |длины Эффективная хэш-функция — односторонняя (однонаправленная) функция, |При использовании которой коллизии возникают очень редко, а ее результат имеет рЬтносительно маленькую установленную длину. Идеальная хэш-функция также легко вычислима. Односторонняя функция— функция, не имеющая такой обратной, с помощью которой можно было бы фактически быстро вычислить первоначальные. Данные по значению хэш-кода. Фраза "коллизии возникают очень редко" означает, что вероятность того, что по двум первоначально различным входным данным будет сгенерирован тот же самый хэш-код, является очень маленькой, и мала вероятность вычисления двух отличающихся входных данных, которые приводят к тому же самому рначению хэш-кода Известные алгоритмы хэширования MD5 и SHA1, как полагают, являются превосходным выбором для использования в цифровом подписании, и оба они поддерживаются в .NET.
Инструкция .ver 1:0:584:39032 указывает окончательную версию сборки SimpleComponent, которая определена частично атрибутом AssemblyVersionAttribute в исходном тексте компонента. Управление версиями более подробно описано в следующем подразделе.
Управление версиями сборки
Как мы только что видели, декларация сборки содержит версию сборки, а также версии каждой из сборок, от которых она зависит. Детальный набор правил, используемых общеязыковой средой выполнения CLR для того, чтобы определить зависимости версии, называют политикой управления версиями. Заданная по умолчанию политика управления версиями определена зависимостями, указанными в декларациях сборки, но при необходимости ее можно изменить в файле конфигурации приложения или в общесистемном файле конфигурации. Автоматическая проверка версии выполняется общеязыковой средой выполнения CLR только на сборках со строгими именами (то есть, на сборках с цифровой подписью). Однако, каждой сборке, независимо от того, как она развернута, должен быть назначен номер версии. Номер версии сборки состоит из следующих четырех полей.
• Главная версия (Major version): Главные несовместимые изменения.
• Младшая версия (Minor version): Менее значительные несовместимые изменения.
• Номер компоновки (Build number): Обратно совместимые изменения, сделанные в ходе разработки.
• Пересмотр (Revision): Обратно совместимые изменения, сделанные в ходе текущего быстрого исправления (Quick Fix Engineering, QFE).
Вышеупомянутые соглашения относительно назначения каждого поля номера версии не предписаны общеязыковой средой выполнения CLR. Именно программист устанавливает эти или любые другие соглашения при проверке совместимости сборки и определении политики управления версиями в файле конфигурации, который мы обсудим позже в этой главе.
Традиционно изменение значения главного или младшего номера указывает явную несовместимость с предыдущей версией. Это используется при существенных изменениях в новом выпуске сборки, и существующие клиенты не могут использовать новую версию. Изменения номера компоновки подразумевают совместимость вниз, и этот номер обычно изменяется каждый раз при очередной компоновке сборки в ходе разработки. Совместимость вниз между номерами компоновки является намеренной; однако, этого, очевидно, не может гарантировать общеязыковая среда выполнения CLR, и потому данное свойство должно быть проверено. Изменение номера пересмотра относится к изменениям, сделанным в ходе текущего быстрого исправления (Quick Fix Engineering, QFE). Это поле обычно используется для срочного исправления, которое общеязыковой средой выполнения CLR считается обратно совместимым, если в файле конфигурации не указано иное назначение этого поля. И снова, общеязыковая среда выполнения CLR не может гарантировать, что изменение, сделанное в ходе текущего быстрого исправления (Quick Fix Engineering, QFE), на 100 процентов обратно совместимо, но совместимость вниз желательна и должна быть тщательно проверена.
Информация, относящаяся к версии, может быть определена в исходном тексте, в атрибуте _assembly::AssemblyVersionAttribute. Класс AssemblyVersionAttribute определен в пространстве имен System: :Runtime: :CompilerServices (Система:: Время выполнения::СотрПег5ешсе5). Если этот атрибут не используется, в декларации сборки по умолчанию задается номер версии 0.0.0.0, который, вообще говоря, является признаком небрежности. В проекте, созданном Мастером проектов на управляемом C++ на основе Библиотеки классов (managed C++ Class Library project wizard), исходный файл Assemblylnfo.cpp автоматически генерируется с версией 1.0.*, т.е. главная версия равна 1, младшая версия — 0, причем значения пересмотра и компоновки генерируются автоматически. Если изменить AssemblyVersionAttribute на, например, "1.1.0.0", как показано ниже, то номер версии, отображенный в декларации, изменится, и будет равен 1:1: 0:0.
//Assemblylnfо.срр
#using <mscorlib.dll>
[_assembly::AssemblyVersionAttribute("1.1.0.0")];
Чтобы не указывать значений пересмотра и компоновки, можно использовать символ звездочка (*). Когда вы вообще определяете какой-либо номер версии, вы должны, как минимум, определить главный номер. Если вы определяете только главный номер, остающиеся значения будут по умолчанию иметь значение нуль. Если вы определяете также младшее значение, то можете опустить оставшиеся поля, которые по умолчанию будут обнулены, или можете указать звездочку, тогда значения будут сгенерированы автоматически. Звездочка в данном случае означает, что значение компоновки будет равняться количеству дней, прошедших с 1 января 2000 года, а значение пересмотра будет установлено равным количеству секунд, прошедших с полуночи, деленному на 2. Если вы определяете значения главного и младшего номеров, а также номера компоновки, причем указываете звездочку для значения пересмотра, то только номер пересмотра будет равен количеству секунд, прошедшему с полуночи, деленному на 2. Когда все четыре поля указаны явно, все четыре значения будут отражены в декларации. Следующие примеры показывают правильные (допустимые) спецификации версии.
Определено в исходном тексте Записано в декларации
Ни одно поле 0:0:0:0
1 1:0:0:0
1.1 1:1:0:0
1.1. * 1:1:464:27461
1.1.43 1:1:43:0
1.1.43.* 1:1:43:29832
1.1.43.52 1:1:43:52
Если указать звездочку, то версия автоматически будет изменяться каждый раз при компоновке компонента; однако каждая новая версия считается обратно совместимой, так как главные и младшие номера не изменяются автоматически. Чтобы определить новую обратно несовместимую версию, вы должны явно изменить главный и/или младший номер версии.

Частное развертывание сборки


Частное развертывание сборки просто означает, что конечный пользователь копирует сборку в тот же самый каталог, что и клиентская программа, использующая ее. Не нужна никакая регистрация, и не требуется никакая причудливая инсталляционная программа. Кроме того, не требуется никакая очистка системного реестра, не нужна также и никакая программа деинсталляции для удаления компонента. Чтобы деинсталлировать сборку, просто удалите ее с жесткого диска.
Конечно, ни один программист из самоуважения никогда не поставит коммерческий компонент, который конечный пользователь должен вручную копировать или удалять какие-либо файлы подобным способом, даже если сделать это очень просто. Пользователи привыкли использовать формальную инсталляционную программу, так что она должна поставляться, даже если ее работа тривиальна. Однако, ручное копирование и удаление сборки — идеальный способ быстрого и безболезненного управления развертыванием реализаций при разработке, тестировании, отладке и испытании. Как вы помните, развертывание компонентов, построенных на основе модели компонентных объектов Microsoft (COM), никогда не было настолько просто. Ведь для развертывания требовался как минимум файл сценария, чтобы занести в системный реестр информацию о компоненте к клиентским программам и о среде времени выполнения модели компонентных объектов Microsoft (СОМ). С появлением сборок не нужно при инсталляции конфигурировать системный реестр, а, значит, позже, когда вы захотите отказаться от компонента, не нужно заботиться о том, чтобы тщательно стереть информацию из системного реестра.
Далее мы рассмотрим, как выполнить частное развертывание сборки для простого NET-компонента. В следующем разделе будет показано, как развернуть общедоступную сборку в глобальном кэше сборок.
Скомпоновав компонент сборки, можно создать клиентскую программу, которая вызывает общедоступные методы компонента Следующий код показывает пример такой клиентской программы, вызывающей общедоступный метод AddEmUp, приведенный ранее. Конечно, в случае необходимости, путь к сборке SimpleComponent.dll в инструкции fusing должен быть откорректирован, чтобы компилятор смог найти нужные данные. Кроме того, сборку нужно развернуть, чтобы общеязыковая среда выполнения CLR могла определить местонахождение сборки и загрузить ее во время выполнения. В этом подразделе развертывание достигается простым копированием сборки в каталог клиентской программы.
//SimpleComponentClient.срр
finclude "stdafx.h"
fusing <mscorlib.dll>
using namespace System;
// использование пространства имен Система;
fusing fusing <C:\OI\NetCpp\Chap7\SimpleComponent\Debug\
SimpleComponent.dll> using namespace SimpleComponent;
// использование пространства имен SimpleComponent;
void main()
{
SomeClass *psc = new SomeClass;
int sum = psc->AddEmUp(3, 4); // суммировать
Console::WriteLine(sum); // сумма
}
Как найти SimpleComponent?
Обратите внимание, что программа SimpleComponentClient имеет инструкцию fusing, указывающую компилятору, где найти сборку SimpleComponent, метаданные которой компилятор использует для контроля соответствия типов. Однако, если вы попробуете выполнить клиентскую программу, то возникнет исключение System. IQ.FileNotFoundException. Так получится потому, что загрузчик класса общеязыковой среды выполнения CLR неспособен найти сборку SimpleComponent. Чтобы выполнить клиент, нужно только скопировать сборку SimpleComponent в тот же самый каталог, где находится программа SimpleComponentClient.ехе.
Теперь можно рассмотреть и сравнить декларацию сборки этой клиентской программы, чтобы увидеть, как она взаимодействует с декларацией сборки SimpleComponent, приведенной ранее. Чтобы рассмотреть декларацию клиентской программы, используйте команду
Ildasm SimpleComponentClient.exe
Можно заметить, что декларация клиентской программы содержит следующую внешнюю зависимость от сборки SimpleComponent.
.assembly extern SimpleComponent
{
.hash = (2A 1C 2D D7 CA 9E 7E D5 08 5B DO 75 23 D3 50 76
5E 28 EA 31 )
.ver 1:0:584:39032
}
Из этого следует, что клиентская программа ожидает использовать сборку SimpleComponent с номером версии 1:0:584:39032. Однако, поскольку сборка развернута частным образом, на самом деле, когда клиент загружает эту сборку, принятая по умолчанию в общеязыковой среде выполнения CLR политика проверки значения версии проверку номера не выполняет. Просто ответственность за то, что в данном конкретном каталоге развернута нужная версия, возлагается на администратора или инсталляционную программу. Эту заданную по умолчанию политику проверки версии можно отменить, используя файл конфигурации. Хотя в клиентской декларации имеется хэш-код компонента, он фактически не используется общеязыковой средой выполнения CLR для того, чтобы проверить подлинность двоичного кода. И снова это происходит потому, что сборка развернута частным образом. В следующем разделе мы увидим, что номер версии и хэш-код используются автоматически для проверки содержимого кода общедоступных сборок, развернутых в глобальном кэше сборок.

Общедоступное развертывание сборки
Кэш сборки — средство параллельного ("бок о бок") развертывания (инсталляции) компонентов на всей машине. Термин "бок о бок" означает, что множество версий того же самого компонента могут постоянно находиться в кэше сборок рядом друг с другом. Глобальный кэш сборок содержит общедоступные сборки, которые являются глобально доступными для всех .NET-приложений на машине. Есть также кэш загружаемых сборок, доступный для приложений типа Internet Explorer, которые автоматически загружают сборки по сети. Чтобы развернуть сборку в глобальном кэше сборок, нужно создать для нее строгое имя.

Строгие имена
Гарантируется, что строгое имя будет глобально уникальным для любой версии любой сборки. Строгие имена генерируются тогда, когда сборка получает цифровую подпись. Это гарантирует, что строгое имя не только уникально, но и может быть сгенерировано только индивидуумом, который имеет секретный ключ.
Строгое имя состоит из простого текстового имени, открытого ключа и хэш-кода, зашифрованного соответствующим секретным ключом. Хэш-код также называется профилем сообщения, а зашифрованный хэш-код— цифровой подписью, электронной подписью и цифровой сигнатурой. Хэш-код фактически эффективно идентифицирует двоичное содержимое сборки, а цифровая сигнатура (подпись) фактически эффективно идентифицирует автора сборки. Все сборки, имеющие одно и то же строгое имя, считаются идентичными (при определении идентичности во внимание принимаются также номера версии). Сборки, строгие имена которых отличаются друг от друга, считаются различными. Полагают, что строгое имя является криптографически стойким, поскольку в противоположность простому текстовому имени, оно однозначно определит сборку на основании ее содержимого и секретного ключа ее автора. Строгое имя имеет следующие полезные свойства:
• гарантирует уникальность, основанную на технологии кодирования;
• устанавливает уникальное пространство имен, основанное на использовании секретного ключа;
• препятствует неправомочному персоналу изменять сборку;
• не позволяет неправомочному персоналу управлять версиями сборки;
• позволяет общеязыковой среде выполнения CLR выполнять проверку содержимого кода общедоступных сборок.

Цифровые сигнатуры (подписи)


Если сборка должна быть развернута в глобальном кэше сборок, то необходимо, чтобы она имела цифровую подпись. Цифровая подпись (сигнатура) не требуется и не особенно полезна для сборки, развернутой частным образом, так как частная сборка развертывается пользователем для того, чтобы работать со своей определенной клиентской программой и потому согласована с ней. Если даже развернутая частным образом сборка имеет цифровую подпись, общеязыковая среда выполнения CLR по умолчанию не проверяет этого, когда загружает сборку для клиентской программы. Поэтому ответственность за предотвращение неправомочной модификации или подтасовки развернутых частным образом сборок полностью возложена на администратора. С другой стороны, очень выгодно использовать общедоступно развернутые (т.е. общедоступные) сборки, так как они должны быть подписаны в цифровой форме, и потому обычно их используют многие клиенты, причем рядом могут существовать несколько версий одной сборки.
Цифровые подписи (сигнатуры) основаны на криптографических методах, в которых применяются открытые ключи. В мире криптографии применяется два основных криптографических метода — симметричные шифры (общий ключ) и асимметричные шифры (открытый ключ). Симметричные шифры совместно используют секретный ключ как для кодирования, так и для расшифровки. Стандарт шифрования данных DES (Data Encryption Standard), Triple DES (Тройной стандарт шифрования данных) и RC2 — примеры симметричных алгоритмов шифрования. Симметричные шифры могут быть очень эффективными и мощными в обеспечении секретности сообщения между двумя доверяющими друг другу сотрудничающими лицами, но они не совсем подходят для ситуаций, где трудно совместно использовать секретный ключ. По этой причине симметричные шифры считаются неподходящими для цифровых подписей (сигнатур). Именно потому цифровые подписи (сигнатуры) используются не для секретности, а лишь для идентификации и опознавания, что является более открытым делом. Если бы вы совместно использовали ваш симметричный ключ с каждым, кто потенциально хотел бы убедиться в подлинности ваших сборок, то по неосторожности могли доверить его людям, которым захотелось исполнить вашу роль. Для использования в цифровых подписях (сигнатурах) намного лучше подходят асимметричные шифры.
Асимметричные шифры, которые также называются шифрами с открытым ключом, используют криптографическую пару открытого и секретного ключа. Ключи в паре математически связаны, и генерируются они вместе; однако чрезвычайно трудно вычислить один ключ по другому. Обычно открытый ключ выдается каждому, кто хотел бы убедиться в подлинности владельца сборки С другой стороны, владелец сохраняет соответствующий секретный ключ подписи в тайне, чтобы никто не мог подделать его подпись. Метод шифрования по схеме открытого ключа RSA (RSA-кодирование) — пример системы шифрования с открытым ключом.
Шифрование с открытым ключом основано на очень интересной математической схеме, которая позволяет зашифровать обычный текст одним ключом, а расшифровать, только зная ключ, соответствующий исходному Например, когда открытый ключ используется, чтобы зашифровать первоначальные данные (называемые открытым текстом), только соответствующий секретный ключ может помочь в расшифровке этого текста. Даже ключ, который использовался для шифрования, не поможет в расшифровке зашифрованного текста! Этот сценарий полезен тогда, когда секретные сообщения посылаются только человеку, который знает секретный ключ.
Рассмотрим теперь противоположный сценарий. Человек, который знает секретный ключ, использует его для того, чтобы зашифровать открытый текст. Получающийся зашифрованный текст не является тайной, так как каждый заинтересованный может получить открытый ключ, чтобы расшифровать данный текст. Этот сценарий бесполезен для сохранения тайны, но очень эффективен для опознавательных целей. Нет необходимости шифровать исходные данные полностью, поэтому, чтобы повысить эффективность, вместо них шифруется компактный хэш-код, который с высокой вероятностью характерен для исходных данных. Если вы получаете файл, который содержит зашифрованную версию его собственного хэш-кода, и расшифровываете его с помощью соответствующего открытого ключа, то фактически вы повторно вычислите хэш-код исходных данных. И если теперь вы обнаружите, что он совпадает с хэш-кодом, который был зашифрован, можете быть совершенно уверены, что именно владелец секретного ключа приложил цифровую подпись и данные не были изменены другими лицами Если предположить, что владелец сумел сохранить тайну секретного ключа, тогда совпадение результатов вычисления доказывает, что никто не смог бы исказить файл после того, как он был подписан в цифровой форме. На рис. 7.3 показано, как работает цифровая подпись (сигнатура).

Цифровое подписание методом шифрования по схеме открытого ключа RSA и SHA1


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

Цифровая подпись и развертывание общедоступной сборки


Чтобы развернуть сборку в глобальном кэше сборок, надо, чтобы она имела цифровую подпись. Разработчики могут разместить сборку в глобальном кэше сборок, используя утилиту Gacutil .exe (Global Assembly Cache utility), Проводник Windows (Windows Explorer) с расширением оболочки Windows посредством просмотра кэша сборок, или.
Инструмент администрирования NET (.NET Admin Tool). Инсталляция общедоступных сборок на конкретной машине конечного пользователя должна быть сделана с помощью программы установки компонентов (системы) по выбору пользователя.
Процесс цифрового подписания сборки включает генерацию криптографической пары открытого и секретного ключа, вычисление хэш-кода сборки, шифровку хэш-кода с помощью секретного ключа, и запись в сборку зашифрованного хэш-кода вместе с открытым ключом.
Зашифрованный хэш-код и открытый ключ вместе составляют полную цифровую сигнатуру (подпись). Обратите внимание, что цифровая подпись (сигнатура) записана в зарезервированную область сборки, не участвующую в вычислении хэш-кода. Когда все это сделано, сборка может быть развернута в глобальном кэше сборок (GAC). Все указанные шаги выполняются тремя простыми инструментальными средствами: утилитой Strong Name (Strong Name utility — Sn. exe), компоновщиком сборок (Assembly Linker — Al.exe) и утилитой Global Assembly Cache (Global Assembly Cache utility — Gacutil.exe). Чтобы скомпоновать, подписать в цифровой форме и развертывать общедоступную сборку, необходимо выполнить следующие шаги:
1. Разработать и скомпоновать компонент.
2. Сгенерировать пару открытого и секретного ключей.
3. Вычислить хэш-код содержимого сборки.
4. Зашифровать хэш-код, используя секретный ключ.
5. Поместить зашифрованный хэш-код в декларацию.
6. Поместить открытый ключ в декларацию.
7. Поместить сборку в глобальный кэш сборок.
Конечно, шаг 1 обычно выполняется с помощью Visual Studio.NET. Шаги 2 — 6 представляют собой цифровое подписание. Шаг 2 выполняется с помощью утилиты Strong Name— Sn.exe. Шаги 3—6 выполняются с помощью Visual Studio.NET или компоновщика сборок — утилиты Assembly Linking — Al. exe ("1" — это "эль", а не "один"). Чтобы на шаге 7 поместить сборку в глобальный кэш сборок, применяется утилита Global Assembly Cache— Gacutil.exe, Проводник Windows (Windows Explorer), или Инструмент администрирования .NET (.NET Admin Tool).
Сейчас мы опишем первый шаг— создание компонента. Для целей демонстрации мы используем пример, подобный предыдущему примеру сборки SimpleComponent, но он называется SharedComponent, и будет развернут в глобальном кэше сборок. Сначала должен быть создан новый проект SharedComponent; для этого используется шаблон Managed C++ Class Library (Управляемый C++ на основе Библиотеки классов), причем нужно добавить следующий код:
//SharedComponent.срр
#include "stdafx.h" // имеет fusing <mscorlib.dll>
#include "SharedComponent.h"
//SharedComponent.h
using namespace System;
// использование пространства имен Система;
namespace SharedComponent
// пространство имен SharedComponent
{
public _gc class SomeClass
// класс сборщика мусора SomeClass
{
public:
int AddEmUpdnt i, int j)
{
return i+j;
}
};
}
На следующем шаге нужно сгенерировать криптографическую пару. Генерацию криптографической пары можно выполнить с помощью утилиты Sn.exe. Эта утилита известна как утилита Strong Name, но иногда также называется и утилитой Shared Name, однако, этот последний термин теперь осуждается. Данный инструмент генерирует криптографически стойкое имя сборки. Вы генерируете криптографическую пару ключей (открытого и секретного) и размещаете ее в файле KeyPair.snk, как показано в следующей команде.
sn -k KeyPair.snk
Получающийся двоичный файл KeyPair. snk не предназначен для чтения пользователю. Но если вы любопытны, можете записать эти ключи в текстовый файл, в котором поля разделяются запятыми. Это делается с помощью следующей команды:
sn -о KeyPair.snk KeyPair.txt
Теперь можете рассмотреть полученный файл с помощью Блокнота (Notepad.exe); однако это не обязательно.
На следующем шаге нужно применить секретный ключ к сборке. Это может быть сделано при компиляции, что, конечно, является полезным для разработки и тестирования; однако, когда придет время промышленного выпуска сборки, нужно будет поместить "строку с названием компании, да и вообще придется использовать более формальный подход. Для защиты корпоративной цифровой подписи предприятия официальный секретный ключ держится в секрете и потому не может быть сообщен программисту. Вместо него программист может при разработке и проверке (испытании) использовать заменяющую криптографическую пару, которая применяется во время компиляции автоматически. Тогда перед выпуском сборки уполномоченный сотрудник ставит официальную корпоративную цифровую сигнатуру (подпись), используя секретный ключ, строго хранимый в тайне. Это делается после компиляции с помощью инструментального средства А1. ехе. Указанный инструмент будет описан в этом подразделе позже. Однако, чтобы во время компиляции применить цифровую сигнатуру (подпись) автоматически, вы просто используете определенный атрибут C++, как показано в следующем коде. В частности, обратите внимание, что файл KeyPair.snk, сгенерированный предварительно инструментом Sn. ехе, определен в атрибуте AssemblyKeyFileAttribute.
//Assemblylnfо.срр
#include "stdafx.h" // имеет fusing <mscorlib.dll>
using namespace System::Reflection;
// использование пространства имен Система::Отражение;
using namespace System::Runtime::CompilerServices;
// использование пространства имен
// Система::Время выполнения:: CompilerServices;
[assembly:AssemblyTitleAttribute(""}];
[assembly:AssemblyDescriptionAttribute("")];
[assembly:AssemblyConfigurationAttribute("")];
[assembly:AssemblyCompanyAttribute("")];
[assembly:AssemblyProductAttribute("")];
[assembly:AssemblyCopyrightAttribute("")];
[assembly:AssemblyTrademarkAttribute("")];
[assembly:AssemblyCultureAttribute("")];
[assembly:AssemblyVersionAttribute("1.0.*") ];
[assembly:AssemblyDelaysignAttribute(false)] ;
[assembly:AssemblyKeyFileAttribute("KeyPair.snk") ];
[assembly:AssemblyKeyNameAttribute("")];
После добавления файла KeyPair. snk к AssemblyKeyFileAttribute, сборку нужно перетранслировать. Тогда при следующем запуске Ildasm. ехе покажет полученную в результате информацию, которая была включена в декларацию сборки для динамически подключаемой библиотеки (DLL) SharedComponent. Обратите внимание, что новая запись называется .publickey. В этой записи содержится открытый ключ создателя, который находится в файле KeyPair. snk. Именно этот открытый ключ может использоваться для расшифровки профиля сообщения, чтобы найти первоначальный хэш-код. Когда сборка развернута в глобальном кэше сборок, этот расшифрованный хэш-код сравнивается с новым, вычисленным по фактическому содержимому сборки, хэш-кодом. Такое сравнение позволяет определить, законна ли сборка (т.е. идентична оригиналу), или незаконна (т.е. разрушена или подделана). Конечно, когда вы используете Sn.exe, эта утилита сгенерирует другую криптографическую пару, и открытый ключ, приведенный ниже, будет отличаться от вашего.
.assembly SharedComponent
{
.publickey = (00 24 00 00 04 80 00 00 94 00 00 00 ...
... 56 5А Bl 97 D5 FF 39 5F 42 DF OF 90 7D D4 )
.hash algorithm 0x00008004
.ver 1:0:584:42238
}
Чтобы проверить разработанную нами сборку SharedComponent, мы должны создать испытательную клиентскую программу, а затем, вместо того, чтобы копировать SharedComponent.dll в каталог клиента, мы применим утилиту Gacutil.exe (Global Assembly Cache utility), или Проводник Windows (Windows Explorer), или Инструмент администрирования .NET (.NET Admin Tool), чтобы развернуть сборку в глобальном кэше сборок. Следующий код представляет собой испытательную клиентскую программу.
//SharedComponentClient.срр
linclude "stdafx.h"
#using <mscorlib.dll>
using namespace Systeir;
// использование пространства имен Система;
#using <C:\OI\NetCpp\Chap7\SharedComponent\Debug\
SharedComponent.dll>
using namespace SharedComponent;
// использование пространства имен SharedComponent;
using namespace System;
// использование пространства имен Система;
void main()
{
SomeClass *psc = new SomeClass;
int sum = psc->AddEmUp(3, 4); // суммируем
Console::WriteLine(sum); // сумма
}
Если бы вышеупомянутая испытательная клиентская программа была выполнена до инсталляции компонента-сборки, во время выполнения было бы запущено исключение FileNotFoundException, потому что сборку не удалось бы найти. Но на сей раз мы развертываем сборку в глобальном кэше сборок с помощью утилиты Gacutil.exe (Global Assembly Cache utility) Напомним, это только один из нескольких методов.
Gacutil -1 SharedComponent.dll
Затем можно выполнить клиент, причем теперь он должен работать надлежащим образом.

После этого вы должны увидеть на консоли сообщение Assembly successfully added to the cache (Сборка успешно добавлена в кэш). В результате выполнения приведенной выше команды в каталоге \WINNT\Assembly был создан новый глобальный узел кэша сборки, имя этого узла — SharedComponent. Как видно на рис. 7.4, номер версии и создатель (т.е. лексема открытого ключа) сборки отображаются в Проводнике Windows (Windows Explorer)
Чтобы установить сборку в глобальный кэш сборок (GAC), можно также использовать Проводник Windows (Windows Explorer) — перетащите и опустите компонент в каталог Assembly. Кроме того, чтобы установить сборку в глобальный кэш сборок (GAC), можно использовать Инструмент администрирования .NET (.NET Admin Tool). Инструмент администрирования .NET (.NET Admin Tool) встроен в ММС и расположен в \WINNT\Microsoft.NET\Framework\vl.0.2914\mscorcfg.msc. Номер версии в каталоге будет отличен в более позднем выпуске .NET Framework. Хотя наличие третьего инструмента может показаться избыточным, эта встроенная в ММС утилита очень полезна, потому что упрощает решение многих задач На рис. 7.5 показано окно верхнего уровня данного инструмента. Чтобы с его помощью добавить сборку в глобальный кэш сборок (GAC), достаточно всего лишь выбрать Assembly Cache в левой области окна, щелкнуть правой кнопкой мыши, и выбрать Add (Добавить). В появившемся диалоговом окне переместитесь к нужному файлу, выберите сборку, которую хотите добавить, и щелкните на кнопке Open (Открыть).
Теперь, когда общедоступная сборка развернута в глобальном кэше сборок, клиентская программа SharedComponentClient может использовать нашу сборку. После того, как вы установили сборку в глобальном кэше сборок (GAC), вы можете переместить клиентскую программу в другой каталог. Вы можете выполнять клиента, причем нет необходимости перемещать сборку, установленную в глобальном кэше сборок (GAC).
Но что случается тогда, когда мы изменяем главную или младшую версию SharedComponent, или подписываем ее другим секретным ключом, а клиентскую программу SharedComponentClient не перекомпоновываем? Если сделать это со сборкой SimpleComponent, развернутой в частном порядке, то общеязыковая среда выполнения CLR не предпринимает никаких попыток обнаружить такое несоответствие (когда действует заданная по умолчанию политика) Однако, если сделать это с общедоступной сборкой, общеязыковая среда выполнения CLR запустит FileNotFoundException, когда обнаружит, что главная или младшая версия либо лексема открытого ключа отличается от того, что было установлено в соответствующем поле при компоновке клиента. Обратите внимание, что это исключение не будет вызвано, если реализация изменена, но главный и младший номер версии не изменены, а сборка подписана тем же самым секретным ключом.

Управление версиями общедоступных компонентов


Как мы видели ранее, чтобы создать новую версию сборки, нужно просто изменить номер версии, который состоит из следующих четырех полей: главный (major) номер, младший (minor) номер, номер компоновки (build) и номер пересмотра (revision). He забывайте, что поля главного и младшего номеров указывают изменения версии, которые не являются обратно совместимыми. Что случается, когда вы устанавливаете две несовместимые версии одной и той же сборки? Чтобы увидеть полученный эффект, попробуйте изменить главный или младший номер версии сборки SharedComponent, которую в предыдущем подразделе мы развернули в глобальном кэше сборок. Ранее была развернута версия 1.0.584.42238 Поэтому, если вы создадите новую версию, у которой младший номер заменен (т. е. версию 1:1 *.*), и развернете ее в глобальном кэше сборок, то с помощью Проводника Windows (Windows Explorer) вы увидите, что доступны обе версии — с различными номерами версий, естественно.

 

Подписание в цифровой форме после компиляции


С развертыванием общедоступных сборок связана еще одна проблема. Шаги, описанные выше, годились для цифрового подписания сборки во время компиляции, так как использовался атрибут, определяющий файл ключей, который содержал открытый и секретный ключи Но часто случается так, что ни один из программистов, разрабатывающих компоненты, которые будут упакованы в сборки, не знает секретного ключа всей организации. В этом случае при разработке и испытании программисты должны использовать временный секретный ключ, но когда придет время отправить сборку клиентам, назначенный представитель компании выполняет окончательное цифровое подписание, используя официальный секретный ключ организации, хранимый в строгой тайне. Это делается при помощи инструмента Sn.exe, с использованием опции -R, где "R" означает "resign" ("подписать заново"). Как правило, предварительно с помощью опции -k утилиты Sn.exe генерируется официальная криптографическая пара. Затем, используя опцию -R утилиты Sn. ехе. ставится подпись на каждой новой сборке.
sn -k TrueKeyPair.snk
sn -R SharedComponent.dll TrueKeyPair.snk
Хотя здесь две команды показаны вместе, обычно не нужно генерировать новую криптографическую пару каждый раз, когда вы заново подписываете очередную новую сборку. После второй команды на пульте появится сообщение Assembly 'SharedComponent.dll' successfully re-signed (Сборка 'SharedComponent.dll' успешно подписана заново).
Впрочем, есть и другой метод: вы можете задержать цифровое подписание. При создании сборки открытый ключ делается доступным компилятору, чтобы он мог поместить его в поле PublicKey декларации сборки. В файле резервируется место для подписи (сигнатуры), но сама подпись (сигнатура) не генерируется. Когда в конечном счете будет сгенерирована фактическая подпись (сигнатура), она помешается в файл с помощью опции -R утилиты Strong Name (sn.exe).
Чтобы указать компилятору, что вы хотите использовать отсроченное цифровое подписание, вы указываете значение true (истина) для атрибута AssemblyDelaySignAttribute в исходном тексте. Вы также должны включить открытый ключ с помощью атрибута
AssemblyKeyFileAttribute.
Предположим, что вы сгенерировали криптографическую пару открытого и секретного ключа так, как описано выше. Тогда вы с помощью опции -р утилиты Strong Name можете получить только открытый ключ, все еще сохраняя в тайне секретный ключ.
sn -p TrueKeyPair.snk PublicKey.snk
Затем вы добавляете следующие два атрибута к вашему коду:
[assembly:AssemblyDelaySignAttribute(true)];
[assembly:AssemblyKeyFileAttribute("PublicKey.snk")];
Сборка все еще не имеет правильной подписи (сигнатуры). Вы не сможете установить ее в глобальном кэше сборок или загрузить ее из каталога приложения. Вы можете отключить проверку подписи (сигнатуры) конкретной сборки, используя опцию -Vr утилиты Strong Name.
sn -Vr SharedComponent.dll
Перед поставкой сборку надо снабдить правильной сигнатурой (подписью), чтобы она могла быть развернута как общедоступная сборка. Для этого используйте опцию -R утилиты Strong Name и запишите криптографическую пару открытого и секретного ключей.
sn -R SharedComponent.dll TrueKeyPair.snk

Резюме


Развертывание очень важно, и составляет одну из главных стадий в разработке программного обеспечения. Если оно не выполнено должным образом, все усилия, потраченные на разработку, становятся пустой тратой времени и денег. К счастью, благодаря сборкам, которые в .NET являются основными единицами развертывания, легко решаются многие сложные проблемы, связанные с развертыванием. Просто создавая динамически загружаемые библиотеки, вы можете получить многократно используемые компоненты без всяческих трудностей, связанных с созданием и установкой компонентов, построенных на основе модели компонентных объектов Microsoft (COM).
Частное развертывание сборки представляет собой не что иное, как просто копирование сборки в тот же самый каталог, в котором расположено приложение-клиент. Для общедоступного развертывания сборки нужно создать строгое имя сборки, а затем развернуть ее в глобальном кэше сборок. Утилита Strong Name (Sn. ехе) создает строгое имя сборки. Потом утилита Gacutil.exe (Global Assembly Cache utility) или .NET Admin Tool (Инструмент администрирования .NET) может использоваться для того, чтобы развернуть общедоступную сборку в глобальном кэше сборок. Кроме того, можно объединить несколько модулей в единую логическую сборку. Чтобы это сделать, необходимо создать отдельные модули без информации, относящейся к декларации, а затем можно сгенерировать модуль декларации для всех модулей, которые включаются в сборку. Мастера CAB и установки, имеющиеся в среде разработки Visual Studio.NET, очень полезны для того, чтобы создать установку стартера и проекты развертывания, — это позволяет сэкономить много времени, которого всегда не хватает на разработку большой системы.

 
На главную | Содержание | < Назад....Вперёд >
С вопросами и предложениями можно обращаться по nicivas@bk.ru. 2013 г. Яндекс.Метрика