Exemplarische Vorgehensweise: Bedarfsgerechtes Herunterladen von Assemblys mit der API für die ClickOnce-Bereitstellung unter Verwendung des Designers

Standardmäßig werden alle in einer ClickOnce-Anwendung enthaltenen Assemblys beim ersten Ausführen der Anwendung heruntergeladen.Möglicherweise werden jedoch bestimmte Teile der Anwendung nur von wenigen Benutzern verwendet.In diesem Fall ist es sinnvoll, eine Assembly erst dann herunterzuladen, wenn Sie einen der zugehörigen Typen erstellen.Die folgende exemplarische Vorgehensweise zeigt, wie Sie bestimmte Assemblys einer Anwendung als "optional" markieren und wie Sie diese unter Verwendung von Klassen im System.Deployment.Application-Namespace herunterladen, wenn die Common Language Runtime sie anfordert.

HinweisHinweis

Die Anwendung muss mit voller Vertrauenswürdigkeit ausgeführt werden, um dieses Verfahren zu verwenden.

HinweisHinweis

Je nach den aktiven Einstellungen oder der Version unterscheiden sich die Dialogfelder und Menübefehle auf Ihrem Bildschirm möglicherweise von den in der Hilfe beschriebenen.Klicken Sie im Menü Extras auf Einstellungen importieren und exportieren, um die Einstellungen zu ändern.Weitere Informationen finden Sie unter Visual Studio-Einstellungen.

Erstellen der Projekte

So erstellen Sie mit Visual Studio ein Projekt mit einer bedarfsabhängigen Assembly

  1. Erstellen Sie in Visual Studio ein neues Windows Forms-Projekt.Zeigen Sie im Menü Datei auf Hinzufügen, und klicken Sie auf Neues Projekt.Wählen Sie im Dialogfeld die Projektvorlage Klassenbibliothek aus, und nennen Sie das Projekt ClickOnceLibrary.

    HinweisHinweis

    In Visual Basic wird empfohlen, die Projekteigenschaften zu bearbeiten, um den Stammnamespace für dieses Projekt in Microsoft.Samples.ClickOnceOnDemand oder einen Namespace Ihrer Wahl zu ändern.Der Einfachheit halber befinden sich die beiden Projekte in dieser exemplarischen Vorgehensweise im gleichen Namespace.

  2. Definieren Sie eine Klasse mit dem Namen DynamicClass und einer einzigen Eigenschaft mit dem Namen 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!");
                }
            }
        }
    }
    
  3. Wählen Sie das Windows Forms-Projekt im Projektmappen-Explorer aus.Fügen Sie einen Verweis auf die System.Deployment.Application-Assembly und einen Projektverweis auf das ClickOnceLibrary-Projekt hinzu.

    HinweisHinweis

    In Visual Basic wird empfohlen, die Projekteigenschaften zu bearbeiten, um den Stammnamespace für dieses Projekt in Microsoft.Samples.ClickOnceOnDemand oder einen Namespace Ihrer Wahl zu ändern.Der Einfachheit halber befinden sich die beiden Projekte in dieser exemplarischen Vorgehensweise im gleichen Namespace.

  4. Klicken Sie mit der rechten Maustaste auf das Formular, klicken Sie im Menü auf Code anzeigen, und fügen Sie dem Formular die folgenden Verweise hinzu.

    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;
    
  5. Fügen Sie den folgenden Code hinzu, um diese Assembly bei Bedarf herunterzuladen.Dieser Code zeigt, wie Sie mit der generischen Dictionary-Klasse einem Gruppennamen mehrere Assemblys zuordnen.Da in dieser exemplarischen Vorgehensweise nur eine Assembly heruntergeladen wird, enthält die Gruppe nur eine Assembly.In einer realen Anwendung würden Sie wahrscheinlich alle Assemblys, die mit einem bestimmten Feature in der Anwendung verknüpft sind, auf einmal herunterladen.Anhand der Zuordnungstabelle ist dies problemlos möglich, indem Sie alle DLLs, die zu einer Funktion gehören, einem Downloadgruppennamen zuordnen.

    ' 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);
    }
    
  6. Klicken Sie im Menü Ansicht auf Toolbox.Ziehen Sie einen Button aus der Toolbox auf das Formular.Doppelklicken Sie auf die Schaltfläche, und fügen Sie dem Click-Ereignishandler den folgenden Code hinzu.

    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);
    }
    

Markieren von Assemblys als optional

So markieren Sie mit Visual Studio Assemblys in der ClickOnce-Anwendung als optional

  1. Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf das Windows Forms-Projekt, und klicken Sie auf Eigenschaften.Wählen Sie die Registerkarte Veröffentlichen aus.

  2. Klicken Sie auf die Schaltfläche Anwendungsdateien.

  3. Suchen Sie die Auflistung für ClickOnceLibrary.dll.Legen Sie das Dropdownfeld Veröffentlichungsstatus auf Einschließen fest.

  4. Erweitern Sie das Dropdownfeld Gruppieren, und wählen Sie Neu aus.Geben Sie den Namen ClickOnceLibrary als neuen Gruppenname ein.

  5. Fahren Sie mit dem Veröffentlichen der Anwendung fort, wie unter Gewusst wie: Veröffentlichen einer ClickOnce-Anwendung mit dem Webpublishing-Assistenten beschrieben.

So markieren Sie Assemblys in der ClickOnce-Anwendung mit dem grafischen Client des Tools zum Generieren und Bearbeiten von Manifesten (MageUI.exe) als optional

  1. Erstellen Sie die ClickOnce-Manifeste, wie unter Exemplarische Vorgehensweise: Manuelles Bereitstellen einer ClickOnce-Anwendung beschrieben.

  2. Wählen Sie vor dem Schließen von MageUI.exe die Registerkarte aus, die das Anwendungsmanifest der Bereitstellung enthält, und wählen Sie auf dieser Registerkarte die Registerkarte Dateien aus.

  3. Suchen Sie ClickOnceLibrary.dll in der Liste der Anwendungsdateien, und legen Sie die Spalte Dateityp auf Kein fest.Geben Sie für die Spalte Gruppieren den Namen ClickOnceLibrary.dll ein.

Testen der neuen Assembly

So testen Sie die bedarfsabhängige Assembly

  1. Starten Sie die mit ClickOnce bereitgestellte Anwendung.

  2. Wenn das Hauptformular angezeigt wird, klicken Sie auf den Button.Nun sollte in einem Meldungsfenster die Zeichenfolge "Hello, World!" angezeigt werden.

Siehe auch

Referenz

ApplicationDeployment