zoukankan      html  css  js  c++  java
  • 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的根目录如下。

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

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

  • 相关阅读:
    The Collections Module内建collections集合模块
    生成器接受和返还功能在执行过程中的详解以及生成器实现协同
    写python中的装饰器
    windows下载Mysql-python
    分别用单线程和多线程运行斐波那契、阶乘和累加和
    TCP客户端和服务器间传输数据遇到的TypeError: a bytes-like object is required, not 'str'问题
    python的property属性
    python的伪私有属性
    使用栈实现中缀表达式转为后缀表达式和后缀表达式的求解
    公众帐号如何向用户发送emoji表情(php版,附emoji编码表)
  • 原文地址:https://www.cnblogs.com/keanuyaoo/p/3357944.html
Copyright © 2011-2022 走看看