Bedarfsgesteuertes Herunterladen von Assemblys mit der ClickOnce-Bereitstellungs-API

Standardmäßig werden alle Assemblys, die in einer ClickOnce-Anwendung enthalten sind, bei der ersten Ausführung der Anwendung heruntergeladen. Möglicherweise gibt es jedoch Teile der Anwendung, die von einer kleinen Gruppe von Benutzer*innen verwendet werden. In diesem Fall soll eine Assembly erst heruntergeladen werden, wenn eine der in ihr definierten Typen erstellt wird. Die folgende exemplarische Vorgehensweise bietet Hinweise zum Markieren bestimmter Assemblys in der Anwendung als „optional“ sowie zum Herunterladen dieser Assemblys, indem Sie Klassen im System.Deployment.Application-Namespace verwenden, wenn diese von der Common Language Runtime (CLR) angefordert werden.

Hinweis

Die Klasse ApplicationDeployment und die APIs im Namespace System.Deployment.Application werden in .NET Core und .NET 5 und höheren Versionen nicht unterstützt. In .NET 7 wird eine neue Methode für den Zugriff auf Anwendungsbereitstellungseigenschaften unterstützt. Weitere Informationen finden Sie unter Zugreifen auf ClickOnce-Bereitstellungseigenschaften in .NET. .NET 7 unterstützt nicht das Äquivalent von ApplicationDeployment-Methoden.

Hinweis

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

Voraussetzungen

Sie benötigen eine der folgenden Komponenten, um diese exemplarische Vorgehensweise abzuschließen:

  • Windows SDK: Das Windows SDK kann aus dem Microsoft Download Center heruntergeladen werden.

  • Visual Studio.

Erstellen der Projekte

Erstellen eines Projekts, das eine bedarfsabhängige Assembly verwendet

  1. Erstellen Sie ein Verzeichnis mit dem Namen „ClickOnceOnDemand“.

  2. Öffnen Sie die Windows SDK-Eingabeaufforderung oder die Visual Studio-Eingabeaufforderung.

  3. Wechseln Sie zum ClickOnceOnDemand-Verzeichnis.

  4. Generieren Sie mithilfe des folgenden Befehls ein Schlüsselpaar aus privaten und öffentlichen Schlüsseln.

    sn -k TestKey.snk
    
  5. Verwenden Sie Editor oder einen anderen Text-Editor, um eine Klasse namens DynamicClass mit einer einzelnen Eigenschaft namens Message zu definieren.

    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!");
                }
            }
        }
    }
    
  6. Speichern Sie den Text abhängig von der verwendeten Sprache als Datei mit dem Namen ClickOnceLibrary.cs bzw. ClickOnceLibrary.vb im ClickOnceOnDemand-Verzeichnis.

  7. Kompilieren Sie die Datei in einer Assembly.

    csc /target:library /keyfile:TestKey.snk ClickOnceLibrary.cs
    
  8. Verwenden Sie den folgenden Befehl, um das öffentliche Schlüsseltoken für die Assembly abzurufen:

    sn -T ClickOnceLibrary.dll
    
  9. Erstellen Sie eine neue Datei mit Ihrem Text-Editor, und geben Sie den folgenden Code ein. Dieser Code erstellt eine Windows Forms-Anwendung, die die ClickOnceLibrary-Assembly herunterlädt, wenn sie erforderlich ist.

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;
    using System.Reflection;
    using System.Deployment.Application;
    using Microsoft.Samples.ClickOnceOnDemand;
    
    namespace ClickOnceOnDemand
    {
        [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand, Unrestricted=true)]
        public class Form1 : Form
        {
            // 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>();
    
            public static void Main()
            {
                Form1 NewForm = new Form1();
                Application.Run(NewForm);
            }
    
            public Form1()
            {
                // Configure form. 
                this.Size = new Size(500, 200);
                Button getAssemblyButton = new Button();
                getAssemblyButton.Size = new Size(130, getAssemblyButton.Size.Height);
                getAssemblyButton.Text = "Test Assembly";
                getAssemblyButton.Location = new Point(50, 50);
                this.Controls.Add(getAssemblyButton);
                getAssemblyButton.Click += new EventHandler(getAssemblyButton_Click);
    
                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," +  
                "Version=1.0.0.0, Culture=en, PublicKeyToken=03689116d3a4ae33");
                    }
                    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);
            }
    
            private void getAssemblyButton_Click(object sender, EventArgs e)
            {
                DynamicClass dc = new DynamicClass();
                MessageBox.Show("Message: " + dc.Message);
            }
        }
    }
    
  10. Suchen Sie im Code den Aufruf von LoadFile.

  11. Legen Sie PublicKeyToken auf den Wert fest, den Sie zuvor abgerufen haben.

  12. Speichern Sie die Datei als Form1.cs bzw. Form1.vb.

  13. Kompilieren Sie sie mithilfe des folgenden Befehls in eine ausführbare Datei.

    csc /target:exe /reference:ClickOnceLibrary.dll Form1.cs
    

Markieren von Assemblys als optional

Markieren von Assemblys als optional in Ihrer ClickOnce-Anwendung mithilfe von MageUI.exe

  1. Erstellen Sie wie unter Exemplarische Vorgehensweise: Manuelles Bereitstellen einer ClickOnce-Anwendung beschrieben mithilfe von MageUI.exe ein Anwendungsmanifest. Verwenden Sie die folgenden Einstellungen für das Anwendungsmanifest:

    • Nennen Sie das Anwendungsmanifest ClickOnceOnDemand.

    • Legen Sie auf der Seite Dateien in der Zeile ClickOnceLibrary.dll die Spalte Dateityp auf Keine fest.

    • Geben Sie auf der Seite Dateien in der Zeile ClickOnceLibrary.dll in der ClickOnceLibrary.dllGruppen-Spalte ein.

  2. Erstellen Sie wie unter Exemplarische Vorgehensweise: Manuelles Bereitstellen einer ClickOnce-Anwendung beschrieben mithilfe von MageUI.exe ein Bereitstellungsmanifest. Verwenden Sie die folgenden Einstellungen für das Bereitstellungsmanifest:

    • Nennen Sie das Bereitstellungsmanifest ClickOnceOnDemand.

Testen der neuen Assembly

So testen Sie die bedarfsabhängige Assembly

  1. Laden Sie Ihre ClickOnce-Bereitstellung auf einen Webserver hoch.

  2. Starten Sie Ihre Anwendung, die mit ClickOnce über einen Webbrowser bereitgestellt wird, indem Sie die URL in das Bereitstellungsmanifest eingeben. Wenn Sie Ihre ClickOnce-Anwendung ClickOnceOnDemand aufrufen und in das Stammverzeichnis von „adatum.com“ hochladen, sieht Ihre URL wie folgt aus:

    http://www.adatum.com/ClickOnceOnDemand/ClickOnceOnDemand.application
    
  3. Wenn das Hauptformular angezeigt wird, drücken Sie die Button. Daraufhin sollte eine Zeichenfolge in einem Meldungsfeldfenster angezeigt werden, die „Hello, World!“ lautet.