Пошаговое руководство. Загрузка сборок по требованию с помощью API развертывания ClickOnce с использованием конструктора
Обновлен: Ноябрь 2007
По умолчанию все сборки, включенные в приложение ClickOnce, загружаются при первом запуске приложения. Однако могут быть части приложения, используемые небольшим числом пользователей. В этом случае необходимо, чтобы сборка загружалась только при создании одного из ее типов. Следующее пошаговое руководство демонстрирует, как пометить определенные сборки в приложении как "необязательные" и как их загрузить при помощи классов в пространстве имен System.Deployment.Application, если они необходимы для среды CLR.
Примечание. |
---|
Чтобы использовать эту процедуру, приложение должно выполняться с полным доверием. |
Примечание. |
---|
Отображаемые диалоговые окна и команды меню могут отличаться от описанных в справке, в зависимости от текущих параметров или версии. Чтобы изменить настройки, в меню Сервис выберите команду Импорт и экспорт параметров. Дополнительные сведения см. в разделе Параметры Visual Studio. |
Создание проектов
Создание проекта, который использует сборку по требованию, при помощи Visual Studio
Создайте в Visual Studio новый проект Windows Forms. В меню Файл выберите команду Добавить, затем выберите пункт Создать проект. В диалоговом окне выберите проект Библиотека классов и назовите его ClickOnceLibrary.
Примечание. В Visual Basic мы рекомендуем изменить свойства проекта, чтобы изменить корневое пространство имен для этого проекта на Microsoft.Samples.ClickOnceOnDemand или на произвольное пространство имен. Для простоты два проекта в этом пошаговом руководстве расположены в одном пространстве имен.
Определите класс с именем DynamicClass и одним свойством Message.
Public Class DynamicClass Sub New() End Sub Public ReadOnly Property Message() As String Get Message = "Hello, world!" End Get End Property End Class
using System; using System.Collections.Generic; using System.Text; namespace Microsoft.Samples.ClickOnceOnDemand { public class DynamicClass { public DynamicClass() {} public string Message { get { return ("Hello, world!"); } } } }
Выберите проект Windows Forms в обозревателе решений. Добавьте ссылку на сборку System.Deployment.Application и ссылку на проект ClickOnceLibrary.
Примечание. В Visual Basic мы рекомендуем изменить свойства проекта, чтобы изменить корневое пространство имен для этого проекта на Microsoft.Samples.ClickOnceOnDemand или на произвольное пространство имен. Для простоты два проекта в этом пошаговом руководстве расположены в одном пространстве имен.
Правой кнопкой мыши щелкните форму, из меню выберите Просмотреть код и добавьте следующие ссылки на форму.
Imports System.Reflection Imports System.Deployment.Application Imports System.Collections.Generic Imports Microsoft.Samples.ClickOnceOnDemand Imports System.Security.Permissions
using System.Reflection; using System.Deployment.Application; using Microsoft.Samples.ClickOnceOnDemand; using System.Security.Permissions;
Добавьте следующий код для загрузки этой сборки по требованию. Этот код показывает, как сопоставить набор сборок имени группы с использованием универсального класса Dictionary. Поскольку в этом пошаговом руководстве мы загружаем только одну сборку, в нашей группе имеется только одна сборка. В реальном приложении, вероятнее всего, нужно будет одновременно загружать все сборки, связанные с одной функцией в приложении. Таблица сопоставления позволяет легко делать это, связывая все библиотеки DLL, относящиеся к функции, при помощи имени группы загрузки.
' Maintain a dictionary mapping DLL names to download file groups. This is trivial for this sample, ' but will be important in real-world applications where a feature is spread across multiple DLLs, ' and you want to download all DLLs for that feature in one shot. Dim DllMappingTable As New Dictionary(Of String, String)() <SecurityPermission(SecurityAction.Demand, ControlAppDomain:=True)> _ Sub New() ' This call is required by the Windows Form Designer. InitializeComponent() ' Add any initialization after the InitializeComponent() call. DllMappingTable("ClickOnceLibrary") = "ClickOnceLibrary" End Sub Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load AddHandler AppDomain.CurrentDomain.AssemblyResolve, AddressOf Me.CurrentDomain_AssemblyResolve End Sub Private Function CurrentDomain_AssemblyResolve(ByVal sender As Object, ByVal args As ResolveEventArgs) As System.Reflection.Assembly Dim NewAssembly As Assembly = Nothing If (ApplicationDeployment.IsNetworkDeployed) Then Dim Deploy As ApplicationDeployment = ApplicationDeployment.CurrentDeployment ' Get the DLL name from the argument. Dim NameParts As String() = args.Name.Split(",") Dim DllName As String = NameParts(0) Dim DownloadGroupName As String = DllMappingTable(DllName) Try Deploy.DownloadFileGroup(DownloadGroupName) Catch ex As Exception MessageBox.Show("Could not download file group from Web server. Contact administrator. Group name: " & DownloadGroupName & "; DLL name: " & args.Name) Throw (ex) End Try ' Load the assembly. ' Assembly.Load() doesn't work here, as the previous failure to load the assembly ' is cached by the CLR. LoadFrom() is not recommended. Use LoadFile() instead. Try NewAssembly = Assembly.LoadFile(Application.StartupPath & "\" & DllName & ".dll") Catch ex As Exception Throw (ex) End Try Else ' Major error - not running under ClickOnce, but missing assembly. Don't know how to recover. Throw New Exception("Cannot load assemblies dynamically - application is not deployed using ClickOnce.") End If Return NewAssembly End Function
// Maintain a dictionary mapping DLL names to download file groups. This is trivial for this sample, // but will be important in real-world applications where a feature is spread across multiple DLLs, // and you want to download all DLLs for that feature in one shot. Dictionary<String, String> DllMapping = new Dictionary<String, String>(); [SecurityPermission(SecurityAction.Demand, ControlAppDomain=true)] public Form1() { InitializeComponent(); DllMapping["ClickOnceLibrary"] = "ClickOnceLibrary"; AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve); } /* * Use ClickOnce APIs to download the assembly on demand. */ private Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) { Assembly newAssembly = null; if (ApplicationDeployment.IsNetworkDeployed) { ApplicationDeployment deploy = ApplicationDeployment.CurrentDeployment; // Get the DLL name from the Name argument. string[] nameParts = args.Name.Split(','); string dllName = nameParts[0]; string downloadGroupName = DllMapping[dllName]; try { deploy.DownloadFileGroup(downloadGroupName); } catch (DeploymentException de) { MessageBox.Show("Downloading file group failed. Group name: " + downloadGroupName + "; DLL name: " + args.Name); throw (de); } // Load the assembly. // Assembly.Load() doesn't work here, as the previous failure to load the assembly // is cached by the CLR. LoadFrom() is not recommended. Use LoadFile() instead. try { newAssembly = Assembly.LoadFile(Application.StartupPath + @"\" + dllName + ".dll"); } catch (Exception e) { throw (e); } } else { //Major error - not running under ClickOnce, but missing assembly. Don't know how to recover. throw (new Exception("Cannot load assemblies dynamically - application is not deployed using ClickOnce.")); } return (newAssembly); }
В меню Вид выберите пункт Панель элементов. Перетащите элемент Button из панели элементов в форму. Дважды щелкните кнопку и добавьте следующий код в обработчик событий Click.
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim DC As New DynamicClass() MessageBox.Show("Message is " & DC.Message) End Sub
private void getAssemblyButton_Click(object sender, EventArgs e) { DynamicClass dc = new DynamicClass(); MessageBox.Show("Message: " + dc.Message); }
Пометка сборок как необязательные
Пометка сборок как необязательные в приложении ClickOnce при помощи Visual Studio
В обозревателе решений щелкните правой кнопкой мыши проект Windows Forms и выберите Свойства. Перейдите на вкладку Публикация.
Нажмите кнопку Файлы приложения.
Найдите список для ClickOnceLibrary.dll. В раскрывающемся списке Состояние публикации выберите Включить.
Раскройте раскрывающийся список Группа и выберите Создать. Введите имя ClickOnceLibrary в качестве имени новой группы.
Продолжите публиковать приложение, как описано в разделе Практическое руководство. Публикация приложения ClickOnce.
Пометка сборок как необязательные в приложении ClickOnce при помощи средства создания и изменения манифеста — графический клиент (MageUI.exe)
Создайте манифест ClickOnce, как описано в разделе Пошаговое руководство. Развертывание приложения ClickOnce вручную.
Перед закрытием MageUI.exe выберите вкладку, содержащую манифест приложения развертывания, и на этой вкладке перейдите на вкладку Файлы.
В списке файлов приложения найдите ClickOnceLibrary.dll и установите для него в столбце Тип файла значение Отсутствует. В столбце Группа введите ClickOnceLibrary.dll.
Проверка новой сборки
Проверка сборки по требованию
Запустите приложение, развернутое при помощи ClickOnce.
Когда появится главная форма, нажмите элемент Button. В окне сообщения должна быть видна строка "Hello, World!".