Tutorial: Descarga de ensamblados a petición con la API de implementación de ClickOnce

De forma predeterminada, todos los ensamblados incluidos en una aplicación de ClickOnce se descargan la primera vez que se ejecuta la aplicación. Sin embargo, puede haber partes de su aplicación que un pequeño conjunto de los usuarios utilice. En tal caso, es probable que quiera descargar un ensamblado solo cuando cree uno de sus tipos. En el siguiente tutorial se muestra cómo marcar determinados ensamblados en la aplicación como “opcionales” y cómo descargarlos usando clases en el espacio de nombres System.Deployment.Application cuando los solicita Common Language Runtime (CLR).

Nota

La clase ApplicationDeployment y las API del espacio de nombres System.Deployment.Application no se admiten en .NET Core y .NET 5 y versiones posteriores. En .NET 7 se admite un nuevo método de acceso a las propiedades de implementación de aplicaciones. Para obtener más información, consulte Acceso a las propiedades de implementación de ClickOnce en .NET. .NET 7 no admite el equivalente de los métodos ApplicationDeployment.

Nota:

La aplicación deberá ejecutarse con plena confianza para poder usar este procedimiento.

Prerrequisitos

Necesitará uno de los componentes siguientes para completar este tutorial:

  • Windows SDK. Windows SDK se puede descargar desde el Centro de descarga de Microsoft.

  • Visual Studio.

Creación de los proyectos

Para crear un proyecto que use un ensamblado a petición

  1. Cree un directorio denominado ClickOnceOnDemand.

  2. Abra el símbolo del sistema de Windows SDK o el símbolo del sistema de Visual Studio.

  3. Cambie al directorio ClickOnceOnDemand.

  4. Genere un par de claves pública y privada con el comando siguiente:

    sn -k TestKey.snk
    
  5. Con el Bloc de notas u otro editor de texto, defina una clase denominada DynamicClass con una sola propiedad llamada Message.

    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. Guarde el texto como archivo denominado ClickOnceLibrary.cs o ClickOnceLibrary.vb, según el idioma que use, en el directorio ClickOnceOnDemand.

  7. Compile el archivo en un ensamblado.

    csc /target:library /keyfile:TestKey.snk ClickOnceLibrary.cs
    
  8. Para obtener el token de clave pública para el ensamblado, use el comando siguiente:

    sn -T ClickOnceLibrary.dll
    
  9. Cree un archivo con el editor de texto y escriba el código siguiente. Este código crea una aplicación de Windows Forms que descarga el ensamblado ClickOnceLibrary cuando se requiere.

    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. En el código, busque la llamada a LoadFile.

  11. Establezca PublicKeyToken en el valor que recuperó anteriormente.

  12. Guarde el archivo como Form1.cs o Form1.vb.

  13. Compílelo como ejecutable con el comando siguiente.

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

Marcar ensamblados como opcionales

Para marcar ensamblados como opcionales en la aplicación ClickOnce con MageUI.exe

  1. Use MageUI.exe para crear un manifiesto de aplicación como se describe en Tutorial: Implementación manual de una aplicación ClickOnce. Use la configuración siguiente para el manifiesto de aplicación:

    • Asigne el nombre ClickOnceOnDemand al manifiesto de aplicación.

    • En la página Archivos, en la fila ClickOnceLibrary.dll, establezca la columna Tipo de archivo en Ninguno.

    • En la página Archivos, en la fila ClickOnceLibrary.dll, escriba ClickOnceLibrary.dll en la columna Grupo.

  2. Use MageUI.exe para crear un manifiesto de implementación como se describe en Tutorial: Implementación manual de una aplicación ClickOnce. Use la configuración siguiente para el manifiesto de implementación:

    • Asigne el nombre ClickOnceOnDemand al manifiesto de implementación.

Probar el nuevo ensamblado

Para probar el ensamblado a petición

  1. Cargue la implementación de ClickOnce en un servidor web.

  2. Inicie la aplicación implementada con ClickOnce desde un explorador web; para ello, escriba la dirección URL en el manifiesto de implementación. Si llama a la aplicación ClickOnce ClickOnceOnDemand y la carga en el directorio raíz de adatum.com, la dirección URL tiene un aspecto similar a este:

    http://www.adatum.com/ClickOnceOnDemand/ClickOnceOnDemand.application
    
  3. Cuando aparezca el formulario principal, pulse el Button. Debería ver una cadena en una ventana de cuadro de mensaje que dice “Hello, World!”.