蝈蝈俊.net

-- 用随笔来记录自己的技术感触
随笔 - 597, 评论 - 4064, 引用 - 276

导航

关于

这里是我的技术Blog,下一代CSDN社区Blog在 http://blog.csdn.net/ghj1976/

标签

每月存档

最新留言

  • re:学习笔记:7种结构型设计模式简单对比
    <p>最新在家创业系统 ----刚从国外引进,市场巨大。 ----在家可经营所有国家生意,事业规模宏大。 ----不需求人与说服;不用放厚脸皮去推销。 ----极小投资;零风险;成...
    by jackielongteng(注册) on 2009/6/14 13:43:56
  • re:作用域
    <p>☆                    &deg;∵☆       &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...
    by jackielongteng(注册) on 2009/6/14 13:03:25
  • re:Html标签嵌套对展示性能的影响
    <p><strong>所有的浏览器都按照你提到的浏览器解析Html规则来解析嘛?</strong></p>
    by Cola(注册) on 2009/6/12 23:07:28
  • re:Html5
    <p>目前来说,HTML5还只是一个梦想,呵呵:)</p>
    by 开心就好(注册) on 2009/6/11 16:31:54
  • re:多线程与SqlConnection.Close
    <p>好服月租型IT服务台,与你共成长! 月租型ITSM软件,注册即可免费体验! 详情请登录官方网站:<a href="http://www.servicezon.co...
    by qzhibo(注册) on 2009/6/3 15:14:21
  • re:多线程Singleton单件模式
    <pre><span style="color: #0000ff;">//Another way public</span> <sp...
    by Yaojian(注册) on 2009/4/22 14:02:35
  • re:Thread.Sleep(0)
    <p>学习了~</p>
    by shuitong888(注册) on 2009/4/8 14:29:24
  • re:Html标签嵌套对展示性能的影响
    <p>DIV固然好 但IE6,7,8 firefox,safari ....做美工的人要累死.</p>
    by ryq1(注册) on 2009/4/3 14:16:25
  • re:用.net 编码实现朗读文本的方法
    <p>我第一次 按键时 能听到声音,但是第二次按键时,没反应。网页一直在 loading.&nbsp;是什么原因?</p>
    by tracytang949(注册) on 2009/3/27 7:01:09
  • re:information_schema.routines与sysobjects
    <p>用sys.procedures多好。</p>
    by luke(注册) on 2009/3/16 16:45:49
  • re:SQL Server 2005 配置发送邮件
    <p>&lt;A href="<a href="http://www.3rt.info">http://www.3rt.info</...
    by ives007(注册) on 2009/2/26 16:47:00
  • re:推荐 Gemini 这个bug管理工具
    <p>你好!首先非常感谢推荐使用Gemini,这段时间在使用Gemini,有些问题想请教以下。</p> <p>1.Create Issue 以后,设置了Visib...
    by CowboyRyan(注册) on 2009/2/20 15:45:08
  • re:推荐 Gemini 这个bug管理工具
    <p>你好!首先非常感谢推荐使用Gemini,这段时间在使用Gemini,有些问题想请教以下。</p> <p>1.Create Issue 以后,设置了Visib...
    by CowboyRyan(注册) on 2009/2/20 15:32:06
  • re:虚机搭配NLB负载平衡时碰到"没有接口可用于安装新的群集"的解决方案
    <p>google newsid</p>
    by iads(注册) on 2009/2/13 17:25:07
  • re:try catch 与线程
    <p>确实是这样的。因为异常机制本质上是堆栈操作,而各线程的堆栈是独立的。</p>
    by st_szr(注册) on 2009/1/21 9:46:05
  • re:try catch 与线程
    <p>没啥啊,线程就是新启动了一个,当然异常不会影响到原有的线程了。</p> <p>你应该在线程里面合适的位置写上自己的捕获代码就行了。</p>
    by laozizhu(注册) on 2009/1/19 16:33:21
  • re:我的2008,征服天堂
    <p>蝈蝈,可惜我帮不了你啊!</p>
    by laozizhu(注册) on 2009/1/19 16:25:45
  • re:try catch 与线程
    <p>呃&hellip;&hellip;是这样的。可怎么处理呢?</p>
    by Anders Liu(注册) on 2009/1/19 11:58:05
  • re:我的2008,征服天堂
    <p>博主是不是去了师部 做了侦查营长呢?</p>
    by huobazi(注册) on 2009/1/9 14:15:33
  • re:我的2008,征服天堂
    <p>@ghj1976:看来真的危机了</p>
    by 开心就好(注册) on 2009/1/9 10:17:37
  • re: 网络带宽的单位
    不过传输的时候,往往还有压缩。
    by luke(匿名) on 2008/12/15 11:00:21
  • re: 网络带宽的单位
    除10不仅仅是为了方便,在传输中,往往加上控制位,所以一个字节往往需要10Bit.
    by 关门放狗(匿名) on 2008/12/13 16:01:30
  • re: 多缓存并存
    对跨进程甚至跨服务器缓存的性能比较怀疑,进程通信和跨服务器通信代价不菲。即使有已有进程外数据可用,如果考虑在进程做份缓存,定期再进程间同步是否更佳?
    by jinglecat(匿名) on 2008/12/12 18:00:05
  • re: 网络带宽的单位
    好像还有一个为了方便换算,厂家使用的是 除10的处理方式的说法:于是100Mb/sec = 100M / 10 = 10M Byte/sec 所以我通常都是用除10而不是除8来做运算的。
    by kentliu(匿名) on 2008/12/11 11:38:55
  • re: 网络带宽的单位
    又不是大S小s
    by luke(匿名) on 2008/12/10 12:04:50

广告

 

默认情况下,首次运行 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 按钮,我们来设置,需要发布的文件。如下图:

VS2005发布设置中,选择需要发布那些文件的按钮位置

 

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

我们在打开的窗口中,设置 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);
}

 

一些问题说明:

Q:上述代码中,如果我们这个组件OnDemandAssembly.dll 有最新版本了,并且发布了,但是客户端还是一个老的版本的话,这个逻辑我们没有处理呀?

A:问题这个问题,就是代表你对 ClickOnce 的原理还是不懂,OnDemandAssembly.dll 有最新版本,那你就必须再重新发布一个版本的ClickOnce代码,这时候发布的版本号就不一样了。客户端下不同版本号的ClickOnce 程序是存在不同目录下的(当然服务器也是一样)。

系统检查到你的新版本程序发布后,会为新的版本号建立目录,这个目录下如果你没有用过OnDemandAssembly.dll 的功能,是不会有OnDemandAssembly.dll 组件的,继而上述问题是可以不用考虑的。

 

参考资料:

MSDN:Downloading Assemblies On Demand with the ClickOnce Deployment API

打印 | 张贴于 2007-06-14 15:10:00 | Tag:.net 编程心得  VS2005相关

留言反馈

#动态决定加载dll多个版本的完美方案 编辑
我们程序现在依赖于cad的一个simple.dll.cad有2004,有2006.这个simple.dll是强命名的,04跟06虽不同但版本号是一样的,不可以放在同一目录下.我们现在的程序需要同时支...
2007-07-01 19:54:00 | [匿名用户:曼迪]
#[转载]动态决定加载dll多个版本的完美方案 编辑
今天看到动态加载DLL的一个不错的实现方案,转载一下。  原文出处:懒猪乐园 再次感谢作者!!!  原文:     最近同事遇到一个问题,关于程序需要在动态的时候决定究竟要加载dll的哪个版本. ...
2007-06-30 22:19:00 | [匿名用户:Brush]
#动态决定加载dll多个版本的完美方案 编辑
最近同事遇到一个问题,关于程序需要在动态的时候决定究竟要加载dll的哪个版本.我们程序现在依赖于cad的一个simple.dll.cad有2004,有2006.这个simple.dll是强命名的,...
2007-06-29 16:55:00 | [匿名用户:Anders06]
#回复: 使用VS2005的 ClickOnce 技术实现按需下载组件 编辑
我都看不懂
2007-06-23 17:23:00 | [匿名用户:LIMENGMENG]
#回复: 使用VS2005的 ClickOnce 技术实现按需下载组件 编辑
谢谢了,我这几天都在找这个呢
2007-06-19 07:50:00 | [匿名用户:LOVE1234]
#回复: 使用VS2005的 ClickOnce 技术实现按需下载组件 编辑
如楼主所说:OnDemandAssembly.dll 有最新版本,那你就必须再重新发布一个版本的ClickOnce代码,这时候发布的版本号就不一样了。客户端下不同版本号的ClickOnce 程序是存在不同目录下的

那么当我对某一dll进行更新后。我希望只对些dll进行更新,或者最多对此组进行更新,用ClickOnce能实现吗?
2007-06-15 17:26:00 | [匿名用户:蚂蚁]
#回复: 使用VS2005的 ClickOnce 技术实现按需下载组件 编辑
附加一段代码,如果你手工编码实现检查升级,可以用如下代码:


private void button2_Click(object sender, EventArgs e)
{
if (ApplicationDeployment.IsNetworkDeployed)
{
ApplicationDeployment ad = ApplicationDeployment.CurrentDeployment;
this.label1.Text = string.Format("Version:{0}", ad.CurrentVersion);
UpdateCheckInfo checkInfo = ad.CheckForDetailedUpdate();
if (checkInfo.UpdateAvailable)
{
ad.Update();
MessageBox.Show("Update Finish");
Application.Restart();
}
}
}

需要注意的是:
你如果在应用程序所在目录下双击Window程序执行这个程序,上述代码中的 ApplicationDeployment.IsNetworkDeployed 返回的是 false, 而不是 true.

你在开始菜单中执行这个程序, ApplicationDeployment.IsNetworkDeployed 返回的才是 true.

2007-06-14 15:21:00 | [匿名用户:ghj1976]
博客主人设置本博客不允许匿名用户发表言论,请登录后再试

Powered by: Joycode.MVC引擎 0.5.1.8