ClickOnce部署(4):下载多个安装包
有时候,我们可能会一次性发布多个安装包,当然在网页上多加几个链接让用户逐个安装也是可取的。不过,也可以弄得更方便些,即用户先安装一个,作为一个"引导程序",然后通过这个程序去下载安装其他应用程序。
我们还是说说真实的例子,这样好理解一点。假设我开发了两个应用程序,一个叫App1,另一个叫App2。我把这两个应用程序同时发布。
我们可以在IIS服务器的根目录下新建两子目录,我们分别把这两个应有程序发布到这两个文件夹下,如下面两张截图所示。

第一个应用

第二个应用
最后,重点是如何做这个"引导"安装包,即我们通过这个应用程序来下载前面两个应用来安装。
别急,在开工之前,我想让大家背书,不多,小学生也能背下来的,总共就两句话:
第一句:凡是和ClickOnce部署有关的类都位于System.Deployment.Application命名空间下。
第二句:开菜单——做菜——试菜——开饭。
第一句话就不用解释了,如果你不明白说明你还没入门。我们把重点放在第二句话,这句话可能大家觉得很搞笑,怎么好像在做饭啊? 是啊,"民以食为天",做饭很重要。
这里说的是做这个"引导"安装应用的步骤,我们要用到InPlaceHostingManager类,它可以实现实时下载安装应用程序包,不要问我这个类在哪里,前面叫你背了第一句话。
InPlaceHostingManager类使 用按以下几步。
第一、new一个InPlaceHostingManager对象,这是废话。构造函数中我们要传 一个URI,部署清单的URI,打包ClickOnce后,那个以.application后缀结尾的文件就是。
第二、开菜单。调用GetManifestAsync方法获取清单,获取后,无论成功与否会引发GetManifestCompleted事件,所以在调用方法前要为GetManifestCompleted事件附加处理代码,这是基础知识,估计我不必解释了。
第三、做菜。调用AssertApplicationRequirements方法检查一下你有没有这个权限,要明白自己是吃几碗饭的,如果权限不够会引发异常,如果力所能及,方法调用后一切正常。一个bool类型的参数表示当权限不足时是否尝试提升,你懂的。
如果权限检查通过,调用DownloadApplicationAsync方法就可以下载应用程序了,在这过程中会引发DownloadProgressChanged和DownloadApplicationCompleted,这两个事件我不说了,你知识怎么处理了,和使用BackgroundWorker一样,如果你不懂,请回家好好细读《C#入门经典》。
第四、试菜。打开"开始"菜单或"开始"屏幕,看看有没有新安装应用的快捷方式,如果有,那就下载安装成功了。
第五、吃饭。尽情享用吧。
好吧,光说不行,还是要做一做。

界面是包括两个Label和两个ProgressBar,标签用来显示文本,进度条当然表示下载的进度。
然后处理Form的Load事件,启动对App1和App2项目的安装包的下载和安装。
public partial class Form1 : Form
{
InPlaceHostingManager appDown1 = null;
InPlaceHostingManager appDown2 = null;
// uris
Uri app1Uri, app2Uri;
public Form1()
{
InitializeComponent();
app1Uri = new Uri(AppMain.Properties.Settings.Default.app1);
app2Uri = new Uri(AppMain.Properties.Settings.Default.app2);
appDown1 = new InPlaceHostingManager(app1Uri, false);
appDown2 = new InPlaceHostingManager(app2Uri, false);
}
private void Form1_Load(object sender, EventArgs e)
{
// 开始下载第一个应用程序
appDown1.GetManifestCompleted += appDown1_GetManifestCompleted;
appDown1.GetManifestAsync();
// 开始下载第二个应用程序
appDown2.GetManifestCompleted += appDown2_GetManifestCompleted;
appDown2.GetManifestAsync();
}
void appDown2_GetManifestCompleted(object sender, GetManifestCompletedEventArgs e)
{
if (e.Error != null)
{
MessageBox.Show(e.Error.Message); return;
}
lblSecond.Text = "即将下载" + e.ProductName + "," + e.Version.ToString();
try
{
appDown2.AssertApplicationRequirements(true);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message); return;
}
appDown2.DownloadProgressChanged += appDown2_DownloadProgressChanged;
appDown2.DownloadApplicationCompleted += appDown2_DownloadApplicationCompleted;
appDown2.DownloadApplicationAsync();
}
void appDown2_DownloadApplicationCompleted(object sender, DownloadApplicationCompletedEventArgs e)
{
lblSecond.Text = "下载完成。";
}
void appDown2_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
this.progressbarSecond.Value = e.ProgressPercentage;
this.lblSecond.Text = "已下载" + e.BytesDownloaded.ToString() + "字节,共" + e.TotalBytesToDownload.ToString() + "字节。";
}
void appDown1_GetManifestCompleted(object sender, GetManifestCompletedEventArgs e)
{
if (e.Error != null)
{
MessageBox.Show("出错:" + e.Error.Message); return;
}
this.lblFirst.Text = "即将下载" + e.ProductName + "," + e.Version.ToString();
try
{
appDown1.AssertApplicationRequirements(true);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
return;
}
appDown1.DownloadProgressChanged += appDown1_DownloadProgressChanged;
appDown1.DownloadApplicationCompleted += appDown1_DownloadApplicationCompleted;
appDown1.DownloadApplicationAsync();
}
void appDown1_DownloadApplicationCompleted(object sender, DownloadApplicationCompletedEventArgs e)
{
lblFirst.Text = "下载完成。";
}
void appDown1_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
this.progressbarFirst.Value = e.ProgressPercentage;
this.lblFirst.Text = "已下载" + e.BytesDownloaded.ToString() + "字节,共" + e.TotalBytesToDownload.ToString() + "字节。";
}
}
而应用安装包的下载地址,我们放到配置文件中,以便修改。
打开项目属性窗口,切换到"设置"选项卡,然后输入App1的下载地址是http://localhost/App1/App1.application;App2的下载地址是http://localhost/App2/App2.application。

VS会为我们生成相应的属性,如上面代码中,我们通过当前应用程序所在的程序集中的.Properties.Settings.Default.app1就可以得到app1的值。
两个应用项目,加上这个用来安装其他应用包的程序,共三个,把它们都发布到指定的路径下。
用来引导的应用就放到根目录,用户只需安装这个就可以了,然后利用这个应用程序来安装其他两个。

App1放到/App1下。

App2放到/App2下。

发布完成后,IIS的根目录如下。

然后安装根目录下的"引导"包。安装后运行应用程序,就会自动下载另外两个安装包并自动安装。

安装完成了,然后打开"开始"菜单或"开始"屏幕,就能看到三个应用程序了。


ClickOnce部署(4):下载多个安装包的更多相关文章
- 如何离线下载Chrome的安装包
打开Chrome官网(自行搜索)点击下载后下载的是联网安装包,这对部分上网不方便的用户造成了一定的麻烦. http://www.google.cn/chrome/browser/desktop/ind ...
- 如何下载flash离线安装包
如何下载flash离线安装包 CreateTime--2018年4月14日16:02:13 Author:Marydon 1.下载地址 UpdateTime--2018年5月13日16点55分 p ...
- python中安装下载超时,下载不了安装包
python3 -m pip install scapy 执行上面命令报错,下载超时,下载不了安装包 Collecting scapy WARNING: Retrying (Retry(total=4 ...
- 无法从NVIDA官网下载安装CUDA安装包?NVIDA官网怎么了?
最近几天由于不知名的原因,导致很多人无法从官网下载NVIDA的CUDA安装包,下载时,浏览器提示此文件可能危害你的计算机,选择保留下载下来也只是一个42字节的exe文件 双击进行安装又出现以下问题: ...
- mysql官网下载linux版本安装包
原文地址:点击打开链接 今天在Linux上部署项目,用到了Mysql,因此想要下载适用于Linux的安装版本,在Mysql官网找了半天,终于找到怎样下载了,这里写出来,以后大家找的时候就好找了. 第一 ...
- Wix 安装部署教程(十三) -- 多语言安装包
这几天摸索WIX的多语言安装包(这里是Wix的setup 工程,不是Bundle),终于走通了,感谢网友uni的指点.WIX的多语言安装包能够根据系统环境自动切换界面语言,你也可以通过命令指定语言.下 ...
- Android下载更新的安装包以及九宫格界面
继上篇博客,我接下来做的是一个九宫格界面,但是对之前的Splash页面我还有要说的就是,当出现网络异常.json解析异常或者没有更新的时候,我们都必须要跳转到我们的主页面,因为Splash页面仅是展示 ...
- 微软MSDN订阅用户已可提前手工下载Windows 10安装包
在Windows 10发布之夜,当全世界都在翘首以盼Windows 10免费发布推送的到来,MSDN订阅用户可以立马享受一项令人项目的特殊待遇:手工下载Windows 10完整安装包+免费使用的激活密 ...
- 下载mysql server安装包的时候,不登录oracle账号,实现下载
需求描述: 之前下载mysql安装包的时候,都是使用oracle账号进行登录下载,最近看到可以不登录账号 就实现下载的方法,在此记录下. 操作过程: 1.选择mysql linux服务器上的安装包,点 ...
随机推荐
- [JSOI2008]完美的对称 题解
题目大意: 首先我们给定一点A以及对称中心S,点A'是点A以S为对称中心形成的像点,即点S是线段AA'的对称中心. 点阵组(X)以S为中心的像点是由每个点的像点组成的点阵组.X是用来产生对称中心S的, ...
- IOS UIWebView 下拉刷新功能的简单实现
1.运行效果图 2.swift 代码的实现 import UIKit class RefreshWebViewController: UIViewController,UIScrollViewDele ...
- Windows下ActiveMQ下载、安装部署
1.下载:http://activemq.apache.org/download.html 最新Windows版本 2.安装 (1) 首先配置JAVA环境变量 JAVA_HOME=D:\Progr ...
- redhat6 yum源配置
第一次接触redhat系统,安装软件时,发现没有ubuntu的apt-get包管理器,自带的yum包管理器又什么都找不到,网上搜了好久,终于把yum配置好了,感谢博主们- 使用redhat系统自带的y ...
- Android APK瘦身之Android Studio Lint (代码审查)
******** ******** 第一部分: 瘦身内容介绍 ******** ******** 项目新版本的迭代接近尾声, 因为历史累积问题, 导致有很多无效的资源让已经臃肿的APK变得更肿, 因此 ...
- 关于iOS后台问题( 一 )(ios后台刷新,后台定位,后台下载,真后台)
关于iOS的后台,以下引用一些文段进行一下脑补,请同学们大致看一下,有个基础,原文出处 -------------------------------------------------------- ...
- vim的配置与使用
经历了一次source insight 一言不合就崩溃之后,决定还是花点时间好好配置和学习以下vim 于是找到大神的配置 https://github.com/humiaozuzu/dot-vimrc ...
- return array 评论添加状态和提示信息
ThinkSNS漏洞系列第一弹,某处处理不当导致SQL注入 漏洞点出现在Comment Widget里:\addons\widget\CommentWidget\CommentWidget.class ...
- HTTP 错误 500.21 - Internal Server Error 处理程序“PageHandlerFactory-Integrated”在其模块列表中有一个错误模块“ManagedPipelineHandler”
HTTP 错误 500.21 - Internal Server Error 处理程序“PageHandlerFactory-Integrated”在其模块列表中有一个错误模块“ManagedPipe ...
- 1035-Spell checker(模糊匹配)
一,题意: 给出一组字典的单词,以'#'结束,之后给出一组要执行模糊匹配的单词序列,以'#'结束 1,若某个单词能在字典中找到,则输出corret 2,若某个单词能通过 变换 或 删除 或 添加一个字 ...