Procedura dettagliata: download di assembly su richiesta con l'API della distribuzione ClickOnce tramite la finestra di progettazione
Per impostazione predefinita, tutti gli assembly inclusi in un'applicazione ClickOnce vengono scaricati alla prima esecuzione dell'applicazione. È tuttavia possibile che alcune parti dell'applicazione vengano utilizzate solo da un set limitato di utenti. In questo caso è preferibile scaricare un assembly solo quando viene creato uno dei relativi tipi. Nella procedura dettagliata riportata di seguito vengono illustrate le operazioni da eseguire per impostare come facoltativi determinati assembly inclusi nell'applicazione e per scaricarli, utilizzando classi dello spazio dei nomi System.Deployment.Application, quando richiesti da Common Language Runtime.
Nota
L'applicazione dovrà essere eseguita in condizioni di attendibilità totale per utilizzare questa procedura.
Nota
È possibile che le finestre di dialogo e i comandi di menu visualizzati siano diversi da quelli descritti nella Guida a seconda delle impostazioni attive o dell'edizione del programma. Per modificare le impostazioni, scegliere Importa/Esporta impostazioni dal menu Strumenti. Per ulteriori informazioni, vedere Gestione delle impostazioni.
Creazione dei progetti
Per creare un progetto che utilizza un assembly su richiesta mediante Visual Studio
Creare un nuovo progetto Windows Form in Visual Studio. Scegliere Aggiungi dal menu File, quindi fare clic su Nuovo progetto. Scegliere un progetto Libreria di classi nella finestra di dialogo e assegnare il nome ClickOnceLibrary a tale progetto.
Nota
In Visual Basic si consiglia di modificare le proprietà del progetto, al fine di cambiare lo spazio dei nomi radice in Microsoft.Samples.ClickOnceOnDemand o in uno spazio dei nomi a propria scelta. Per semplicità, i due progetti in questa procedura dettagliata si trovano nello stesso spazio dei nomi.
Definire una classe DynamicClass con una singola proprietà 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!"); } } } }
Selezionare il progetto Windows Form in Esplora soluzioni. Aggiungere un riferimento all'assembly System.Deployment.Application e un riferimento al progetto ClickOnceLibrary.
Nota
In Visual Basic si consiglia di modificare le proprietà del progetto, al fine di cambiare lo spazio dei nomi radice in Microsoft.Samples.ClickOnceOnDemand o in uno spazio dei nomi a propria scelta. Per semplicità, i due progetti in questa procedura dettagliata si trovano nello stesso spazio dei nomi.
Fare clic con il pulsante destro del mouse sul form, scegliere Visualizza codice dal menu di scelta rapida, quindi aggiungere i seguenti riferimenti al form.
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;
Aggiungere il seguente codice per scaricare l'assembly su richiesta. Questo codice consente di eseguire il mapping di un set di assembly su un nome di gruppo utilizzando una classe Dictionary generica. Nel gruppo è presente un solo assembly perché la procedura dettagliata prevede che ne venga scaricato solo uno. Se si trattasse di una vera applicazione, verrebbero scaricati contemporaneamente tutti gli assembly relativi a un'unica funzionalità nell'applicazione. La tabella di mapping consente di eseguire questa operazione facilmente, associando tutte le DLL che appartengono a una funzionalità a un nome per il gruppo di download.
' 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); }
Scegliere Casella degli strumenti dal menu Visualizza. Trascinare un controllo Button dalla Casella degli strumenti nel form. Fare doppio clic sul pulsante e aggiungere il seguente codice al gestore eventi 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); }
Impostazione degli assembly come facoltativi
Per impostare come facoltativi gli assembly nell'applicazione ClickOnce mediante Visual Studio
In Esplora soluzioni fare clic con il pulsante destro del mouse sul progetto Windows Form e scegliere Proprietà. Fare clic sulla scheda Pubblica.
Scegliere il pulsante File applicazione.
Individuare l'elenco relativo al file ClickOnceLibrary.dll. Impostare la casella di riepilogo a discesa Stato pubblicazione su Includi.
Selezionare Nuovo dalla casella di riepilogo a discesa Gruppo. Immettere il nome ClickOnceLibrarycome nuovo nome del gruppo.
Continuare con la pubblicazione dell'applicazione come descritto in Procedura: pubblicare un'applicazione ClickOnce mediante la Pubblicazione guidata.
Per impostare come facoltativi gli assembly nell'applicazione ClickOnce mediante lo strumento client con interfaccia grafica per la generazione e la modifica di manifesti (MageUI.exe)
Creare i manifesti ClickOnce come descritto in Procedura dettagliata: distribuzione manuale di un'applicazione ClickOnce.
Prima di chiudere MageUI.exe, scegliere la scheda che contiene il manifesto di distribuzione, quindi fare clic sulla scheda File.
Individuare il file ClickOnceLibrary.dll nell'elenco di file dell'applicazione e impostare la relativa colonna Tipo file su Nessuno. Per la colonna Gruppo digitare ClickOnceLibrary.dll.
Test del nuovo assembly
Per testare l'assembly su richiesta
Avviare l'applicazione distribuita con ClickOnce.
Quando viene visualizzato il form principale, scegliere il controllo Button. Verrà visualizzata una finestra di messaggio contenente la stringa "Hello, World!".