运行时自更新程序的.NET实现

  • 面对的主要问题

      运行时自更新程序在实现上面对的主要问题上什么呢?

      先说“更新”一词,“更新”有时也叫“升级”,“更新”程序的过程实际上就是以新的程序文件替换旧的程序文件的过程。在现实中,程序文件通常是由 .exe、.dll 以及其它的诸如xml,ini之类的用于配置的文件组成。在本文中是指.exe,.dll这些包含程序代码的文件。

      “运行时更新”的主要问题是 .exe、.dll 文件在程序运行的时候会被系统锁定,因而进行文件替换的时候会被系统阻止。而如果把程序停止了再进行升级的话,而且无法由要升级的程序自身完成,得借助另一个程序完成,换句话说这不叫“运行时升级”了。本文里的“运行时升级”是指不中断正在运行的程序而同时进行程序文件的升级替换,升级完成后的新功能会在程序的下次运行后得以展现。

  • 应用程序域(AppDomain)和影子拷贝(ShadowCopy)

      在 .NET 中实现这点有着特别的便利,其中主要涉及到两个概念:应用程序域(AppDomain)、影子拷贝(ShadowCopy)。进程是用于在同一计算机上隔离不同的应用程序的,而在 .NET 的托管程序中,应用程序域(AppDomain)是比进程的范围更小的、更安全、用途更广泛的应用程序的隔离单元。这样在一个进程中,可以有多个不同的应用程序域,每个应用程序域可以独立运行一个应用程序而不会相互影响,某个应用程序的错误也不会影响其它的程序,并且每一个AppDomain中的应用程序都可以独立地加载和卸载。影子拷贝(ShadowCopy)是应用应用程序域(AppDomain)的一项特性。通常 AppDomain 加载应用程序时,公共语言运行库会将程序集文件锁定,因此只有卸载了程序集之后才能更新该文件。将 AppDomain 配置为影子拷贝(ShadowCopy)时,来自应用程序路径的程序集文件被复制到另一个位置并从该位置进行加载。这些程序集副本被锁定,但原始程序集文件将取消锁定并可以进行更新。本人的方案就是基于此实现的。

  • 潜在的问题

      似乎按照上面提到的应用程序域(AppDomain)和影子拷贝(ShadowCopy)的特性就可以直接达到目的了,还需要考虑什么吗?可惜的是,现实生活中,通往成功的道路通常都不是一帆风顺的。.NET托管程序中有一个默认程序域,它是.NET托管程序启动后的创建的第一个应用程序域,它与其它时候创建的应用程序域大部分没什么区别,但是却有一点影响到了本文主题的实现,那就是默认程序域是无法开启影子拷贝(ShadowCopy)特性的。那怎么办?那就在在默认程序域中创建一个新的AppDomain来加载实际需要运行的应用程序的程序集。没错,只能这样了,可是这个解决得并不彻底。运行在非默认程序域中的应用程序由于开启ShadowCopy特性而得以运行时更新了,可是从默认程序域创建并加载目标应用程序到新的AppDomain的这一个过程的逻辑还是无法运行时更新,可能通常情况下这一加载的逻辑并不需要升级,可谁又能保证这一点呢,因为我们都知道的一个道理是“真正不变的是变化”。为了彻底地解决这一问题,文本提出了以下的解决方案。

  • 实现方案

      方案中由以下的4个要素组成,并通过以恰当的方式组织这4个要素以实现本文的目标。4个要素如下:

  1. 主程序:是提供应用程序所有业务功能的程序,它要在持续运行的状态中被更新。
  2. 外壳程序:这是进程的真正入口,外壳程序启动后,在其默认程序域中创建新的应用程序域并配置影子拷贝加载主程序。
  3. 外壳加载dll类库:使用外壳程序进行加载主程序的逻辑被封装dll类库,主程序引用类库,外壳程序被作为资源嵌入到类库中。
  4. 更新程序:更新主程序的程序。更新的功能也可以是主程序的一部分,在此只是为了更明晰地表达而将更新功能独立出来。

      实现的基本思路如下:外壳程序是以嵌入资源的方式包含在类库中。当主程序引用类库执行加载操作时,将根据当前的程序域中的属性中是否存在外壳程序设置的标识以确定当前是处于默认程序域中,还是已经由外壳程序加载。如果处于默认程序域,则将外壳程序释放到临时文件夹中启动,并将主程序的入口文件作为参数传递给外壳程序,外壳程序则根据参数,在一个新的应用程序域中加载主程序。主程序和外壳程序的执行流程图如下:

执行流程图

 

      外壳加载类库的实现

  

      主程序入口的实现

 

      外壳程序的实现

 

 

 附件:完整实现的源码

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值