Exemplarische Vorgehensweise: Herunterladen von Assemblys bei Bedarf mit der API für die ClickOnce-Bereitstellung

Standardmäßig werden alle in einer ClickOnce-Anwendung enthaltenen Assemblys beim ersten Ausführen der Anwendung heruntergeladen.Möglicherweise werden aber 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 sie von der Common Language Runtime (CLR) angefordert werden.

HinweisHinweis

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

Vorbereitungsmaßnahmen

Zum Durchführen dieser exemplarischen Vorgehensweise benötigen Sie eine der folgenden Komponenten:

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

  • Visual Studio.

Erstellen der Projekte

So erstellen Sie ein Projekt mit einer bedarfsgesteuerten Assembly

  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 mit dem folgenden Befehl ein Schlüsselpaar aus öffentlichem und privatem Schlüssel:

    sn -k TestKey.snk
    
  5. Definieren Sie in Editor oder einem anderen Text-Editor eine Klasse mit dem Namen DynamicClass und einer einzelnen 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!");
                }
            }
        }
    }
    
  6. Speichern Sie den Text je nach verwendeter Sprache als Datei mit dem Namen ClickOnceLibrary.cs oder ClickOnceLibrary.vb im ClickOnceOnDemand-Verzeichnis.

  7. Kompilieren Sie die Datei in eine Assembly.

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

    sn -T ClickOnceLibrary.dll
    
  9. Erstellen Sie eine neue Datei im Text-Editor, und geben Sie den folgenden Code ein.Durch diesen Code wird eine Windows Forms-Anwendung erstellt, durch die die ClickOnceLibrary-Assembly, falls angefordert, heruntergeladen wird.

    Imports System
    Imports System.Windows.Forms
    Imports System.Deployment.Application
    Imports System.Drawing
    Imports System.Reflection
    Imports System.Collections.Generic
    Imports Microsoft.Samples.ClickOnceOnDemand
    
    
    Namespace Microsoft.Samples.ClickOnceOnDemand
       <System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand, Unrestricted:=true)> _
       Class Form1
          Inherits 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. 
            Dim DllMapping as Dictionary(Of String, String) = new Dictionary(of String, String)()
    
          Public Sub New()
             ' Add button to form.
                Dim GetAssemblyButton As New Button()
                GetAssemblyButton.Location = New Point(100, 100)
                GetAssemblyButton.Text = "Get assembly on demand"
                AddHandler GetAssemblyButton.Click, AddressOf GetAssemblyButton_Click
    
                Me.Controls.Add(GetAssemblyButton)
    
                DllMapping("ClickOnceLibrary") = "ClickOnceLibrary"
                AddHandler AppDomain.CurrentDomain.AssemblyResolve, AddressOf CurrentDomain_AssemblyResolve
          End Sub
    
            <STAThread()> _
            Shared Sub Main()
                Application.EnableVisualStyles()
                Application.Run(New Form1())
            End Sub
    
            Private Function CurrentDomain_AssemblyResolve(ByVal sender As Object, ByVal args As ResolveEventArgs) As Assembly
                If ApplicationDeployment.IsNetworkDeployed Then
                    Dim deploy As ApplicationDeployment = ApplicationDeployment.CurrentDeployment
    
                    ' Get the DLL name from the Name argument.
                    Dim nameParts() as String = args.Name.Split(",")
                    Dim dllName as String = nameParts(0)
            Dim downloadGroupName as String = DllMapping(dllName)
    
                    Try
                        deploy.DownloadFileGroup(downloadGroupName)
                    Catch de As DeploymentException
    
                    End Try
    
                    ' Load the assembly.
                    Dim newAssembly As Assembly = Nothing
    
                    Try
                        newAssembly = Assembly.LoadFile(Application.StartupPath & "\\" & dllName & ".dll," & _  
                "Version=1.0.0.0, Culture=en, PublicKeyToken=03689116d3a4ae33")
                    Catch ex As Exception
                        MessageBox.Show("Could not download assembly on demand.")
                    End Try
    
                    CurrentDomain_AssemblyResolve = newAssembly
                Else
                    CurrentDomain_AssemblyResolve = Nothing
                End If
            End Function
    
            Private Sub GetAssemblyButton_Click(ByVal sender As Object, ByVal e As EventArgs)
                Dim ourClass As New DynamicClass()
                MessageBox.Show("DynamicClass string is: " + ourClass.Message)
            End Sub
        End Class
    End Namespace
    
    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 zuvor abgerufenen Wert fest.

  12. Speichern Sie die Datei entweder als Form1.cs oder Form1.vb.

  13. Kompilieren Sie sie mit dem folgenden Befehl in eine ausführbare Datei.

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

Markieren von Assemblys als optional

So markieren Sie Assemblys in der ClickOnce-Anwendung mit MageUI.exe als optional

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

    • Nennen Sie das Anwendungsmanifest ClickOnceOnDemand.

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

    • Geben Sie auf der Seite Dateien in der Zeile für die ClickOnceLibrary.dll in der Spalte Gruppe den Namen ClickOnceLibrary.dll ein.

  2. Verwenden Sie MageUI.exe, um ein Bereitstellungsmanifest zu erstellen, wie in Exemplarische Vorgehensweise: Manuelles Bereitstellen einer ClickOnce-Anwendung beschrieben.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 die ClickOnce-Bereitstellung auf einen Webserver herauf.

  2. Starten Sie die mit ClickOnce bereitgestellte Anwendung über einen Webbrowser, indem Sie die URL zum Bereitstellungsmanifest eingeben.Wenn Sie der ClickOnce-Anwendung den Namen ClickOnceOnDemand geben und sie in das Stammverzeichnis von adatum.com heraufladen, sieht die URL folgendermaßen aus:

    http://www.adatum.com/ClickOnceOnDemand/ClickOnceOnDemand.application
    
  3. 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