演练:使用 ClickOnce 部署 API 按需下载程序集
默认情况下,ClickOnce 应用程序中包含的所有程序集都会在应用程序首次运行时进行下载。 但是,可能有一小部分用户使用部分应用程序。 在这种情况下,你希望仅当创建其类型之一时才下载程序集。 下面的演练演示如何将应用程序中的某些程序集标记为“可选”,以及如何在公共语言运行时 (CLR) 需要它们时使用 System.Deployment.Application 命名空间中的类下载它们。
注意
.NET Core 和 .NET 5 及更高版本中不支持 System.Deployment.Application 命名空间中的 ApplicationDeployment 类和 API。 在 .NET 7 中,支持一种访问应用程序部署属性的新方法。 有关详细信息,请参阅访问 .NET 中的 ClickOnce 部署属性。 .NET 7 不支持等效的 ApplicationDeployment 方法。
注意
应用程序必须在完全信任下运行才能使用此过程。
先决条件
你将需要以下组件之一来完成本演练:
Windows SDK。 可以从 Microsoft 下载中心下载 Windows SDK。
Visual Studio。
创建项目
创建使用按需程序集的项目
创建名为 ClickOnceOnDemand 的目录。
打开 Windows SDK 命令提示符或 Visual Studio 命令提示符。
更改为 ClickOnceOnDemand 目录。
使用以下命令生成公钥/私钥对:
sn -k TestKey.snk
使用记事本或其他文本编辑器定义名为
DynamicClass
的类,它具有名为Message
的单个属性。将文本另存为名为 ClickOnceLibrary.cs 或 ClickOnceLibrary.vb 的文件(具体取决于你使用的语言),并保存到 ClickOnceOnDemand 目录。
将该文件编译为程序集。
若要获取程序集的公钥令牌,请使用以下命令:
sn -T ClickOnceLibrary.dll
使用文本编辑器创建新文件并输入以下代码。 此代码会创建 Windows 窗体应用程序,该应用程序在需要时下载 ClickOnceLibrary 程序集。
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); } } }
在代码中,找到对 LoadFile 的调用。
将
PublicKeyToken
设置为之前检索到的值。将文件另存为 Form1.cs 或 Form1.vb。
使用以下命令将该文件编译为可执行文件。
将程序集标记为可选
使用 MageUI.exe 在 ClickOnce 应用程序中将程序集标记为可选
使用 MageUI.exe 创建应用程序清单,如演练:手动部署 ClickOnce 应用程序中所述。 对应用程序清单使用以下设置:
将应用程序清单命名为
ClickOnceOnDemand
。在“文件”页上的“ClickOnceLibrary.dll”行中,将“文件类型”列设置为“无”。
在“文件”页上的“ClickOnceLibrary.dll”行中,在“组”列中键入
ClickOnceLibrary.dll
。
使用 MageUI.exe 创建部署清单,如演练:手动部署 ClickOnce 应用程序中所述。 对部署清单使用以下设置:
- 将部署清单命名为
ClickOnceOnDemand
。
- 将部署清单命名为
测试新程序集
测试按需程序集
将 ClickOnce 部署上传到 Web 服务器。
通过输入部署清单的 URL,从 Web 浏览器启动使用 ClickOnce 部署的应用程序。 如果调用 ClickOnce 应用程序
ClickOnceOnDemand
,并将其上传到 adatum.com 的根目录,则 URL 如下所示:http://www.adatum.com/ClickOnceOnDemand/ClickOnceOnDemand.application
在主窗体显示时按 Button。 应在消息框窗口中看到一个显示为“Hello, World!”的字符串。