使用VS2005的 ClickOnce 技术实现按需下载组件

简介:

默认情况下,首次运行 ClickOnce 应用程序时,会下载该应用程序中包含的所有程序集。但是一些特殊的场景我们可能不希望它这么干,而是希望按照一定规测或者需要用到某个组件的时候再下载。

比如我们可能会有下面一些应用场景的需求:

1、我开发的这个客户端程序是要收费的。但是免费用户也可以使用部分功能。我在技术实现上把收费用户使用的功能封装到了A.dll 组件了,我希望免费用户根本无法获得A.dll,只有收费用户才能获得A.dll,并加载A.dll中的收费功能。

2、我整个应用程序非常大,我不希望我每次更新,用户都需要把所有应用程序都下载下来,用户应该只需要下载他用到的功能组件。

下面我们就来实现一个简单的按需下载的例子,我们完全可以在这个例子基础上,实现上述提到的应用场景1。

演示步骤:

一、新建一个 类库 Project

定义类库输出应用程序名为:OnDemandAssembly,即这个类库编译后产生的文件名为 OnDemandAssembly.dll

这个类库中有如下代码,我们用这段代码来模拟上面提到场景中的一些需要按需加载的功能或者是收费的功能,我们将在主程序中调用这个功能:

using System;

namespace OnDemandAssembly
{
public class DynamicClass
{
public string Message
{
get
{
return "郭红俊测试ClickOnce按需加载功能。";
}
}

}
}

二、新建一个 Window 应用程序

我们将在这个Window 应用程序中加载上述类库。

为了便于我们演示这个程序,请确保这个Window程序具备以下功能:

1、有一个 textbox 控件,这个控件在 Window 的OnLoad 事件中,把应用程序的目录显示在这里,方便我们去监控是否上述 OnDemandAssembly.dll 组件被加载了。

代码如下:

private void Form1_Load(object sender, EventArgs e)
{
this.textBox1.Text = Application.StartupPath;
}

2、由一个 Button 按钮,点击这个按钮后,我们把 OnDemandAssembly.dll 组件中的 Message 信息显示出来,代码如下:

private void button1_Click(object sender, EventArgs e)
{
DynamicClass o = new DynamicClass();
MessageBox.Show(o.Message);
}

Window程序关于ClickOnce设置比较特殊的地方:

我们来配置ClickOnce发布的一些特殊参数,确保可以按需下载需要的组件

本文中没有详细描述ClickOnce设置的各个步骤和参数,如果你对ClickOnce不是很熟悉,建议你首先看一些ClickOnce的入门文章再来看本文。

比如:http://blog.oracle.com.cn/155011/viewspace_3603.html 这里提供的ClickOnce 文章(这里是提供了一个word压缩文件下载,文章在压缩的Word文件中)

选择我们的Window程序,在右键菜单中选择属性,在属性页中选择发布(Publish)标签页。

然后点击 Application File 按钮,我们来设置,需要发布的文件。如下图:

上述按钮打开的窗口如下:

我们在打开的窗口中,设置 OnDemandAssembly.dll 文件的 发布状态为 Include,

并在 Download Group 中为OnDemandAssembly.dll 文件新建的一个下载组,我们这里把这个新的下载组命名为 DemandAssembly01 。

说明:

默认情况下,我们用ClickOnce 第一次安装,或者升级程序的时候,系统只下载 Required 组的文件,其他组的文件系统不下载,需要我们自己编码来下载。

其他ClickOnce的设置跟我们平常使用的时候一样来设置。本文忽略这部分。

我们这时候发布这个程序,我们下载安装后,就会发现OnDemandAssembly.dll 文件不在安装目录下,点击这个程序的按钮,就会报异常,找不到需要的应用程序集

OnDemandAssembly.dll 组件。

下面我们来编码实现,如果应用程序找不到 OnDemandAssembly.dll 组件,就从网上下载这个组件的功能

1、窗口的构造函数中增加 AssemblyResolve 事件的处理逻辑

public Form1()
{
InitializeComponent();

AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
}

Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{

}

说明:AppDomain.AssemblyResolve 事件 在对程序集的解析失败时发生。

2、下面我们编码实现 AssemblyResolve 事件的处理逻辑

using System.Reflection;
using System.Deployment.Application;

// 如果我们有多个文件都需要按需下载的话,每个文件影射到那个下载分组,就是这个实体来记录的

Dictionary<String, String> DllMapping = new Dictionary<String, String>();

public Form1()
{
InitializeComponent();
DllMapping["OnDemandAssembly"] = "DemandAssembly01";
AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
}

Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
Assembly newAssembly = null;

// 是 ClickOnce 部署方式
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);
}




本文转自94cool博客园博客,原文链接:http://www.cnblogs.com/94cool/archive/2010/03/31/1701562.html,如需转载请自行联系原作者 

相关文章
|
2月前
|
缓存 安全 前端开发
Electron on macOS: 揭秘 MacUpdater 如何实现无缝自动更新?
本文首发于微信公众号“前端徐徐”,详细探讨了 Electron 应用在 macOS 平台上的更新原理。文章分析了 `MacUpdater` 类的实现,包括与 Electron 原生更新器的集成、更新检测和下载、代理服务器管理、环境适配、安全性保障、错误处理和日志记录、更新安装流程控制以及缓存管理等关键功能。通过这些技术细节,展示了如何在 macOS 上实现高效、安全的 Electron 应用更新。
92 0
Electron on macOS: 揭秘 MacUpdater 如何实现无缝自动更新?
|
2月前
|
API C# Windows
【C#】在winform中如何实现嵌入第三方软件窗体
【C#】在winform中如何实现嵌入第三方软件窗体
140 0
|
Web App开发 Unix 开发者
推荐一款非常优雅且面向开发者的Chrome浏览器插件:在云端
【在云端】是由一群编程开发人员利用业余时间设计开发的一款Chrome浏览器新标签页美化插件,体现摄影美学、专注力以及先进云技术的插件。力求可以通过这项工作使得大家在这个快节奏的社会能够体会到一片安静与祥和,且不被这个时代淘汰。
10251 4
推荐一款非常优雅且面向开发者的Chrome浏览器插件:在云端
|
前端开发 JavaScript API
openHarmony系统组件学习
openHarmony系统应用开发的组件很多,本篇文章仅以一个例子作为一个通用的学习方法,如果之前学过安卓开发,这部分内容应该除了语言,其他没有任何难度,本篇文章参考官网实现一个dialog组件,开始了~~
184 0
openHarmony系统组件学习
|
应用服务中间件 Linux Serverless
搭建Vue3组件库:第十四章 使用Vercel部署在线文档
介绍如何使用Vercel来部署我们的在线文档
514 0
搭建Vue3组件库:第十四章 使用Vercel部署在线文档
|
Web App开发 C++ Windows
C#-clickonce部署和调用
ClickOnce 是一种部署技术,使用它可以用来进行应用程序的自动更新,也可以使用在浏览器中直接调用部署好的应用程序。
233 0
|
小程序 物联网 测试技术
HaaS UI小程序解决方案应用分发之三:应用和版本管理
应用创建和版本管理是应用分发的核心功能之一,新应用在开发完成上线前,需要到应用分发平台申请应用的唯一标识appId一起打包,然后将打包后的升级文件上传到应用分发平台,设备在开机或定时发起升级检测请求时,会将最新的应用版本信息下发到设备进行版本更新。
289 15
HaaS UI小程序解决方案应用分发之三:应用和版本管理
ADI
|
JavaScript 前端开发
[分享] Vue移动端项目配合第三方ui库快速搭建开发环境
[分享] Vue移动端项目配合第三方ui库快速搭建开发环境
ADI
188 0
|
资源调度 JavaScript 测试技术
day-ui 组件库打包环境配置
本小节我们把写好的库打包发布到 npm 上。之后我们建个小 vue3 的项目,安装我们自己的包。实现全加载和按需加载
440 0
day-ui 组件库打包环境配置
|
C#
C#使用Xamarin开发可移植移动应用(5.进阶篇显示弹出窗口与通讯中心)附源码
原文:C#使用Xamarin开发可移植移动应用(5.进阶篇显示弹出窗口与通讯中心)附源码 前言 系列目录 C#使用Xamarin开发可移植移动应用目录 源码地址:https://github.com/l2999019/DemoApp 可以Star一下,随意 - - 说点什么.
1241 0