使用 SmartAssembly 进行智能客户端






4.78/5 (13投票s)
2003年12月25日
8分钟阅读

170744

4081
一种使用“拉取模型”保持应用程序程序集最新状态的解决方案。
引言
对于运行信息系统的组织来说,保持桌面应用程序的所有实例与最新版本的可执行文件、库、配置和其他文件同步是一个常见问题。这总是需要大量的资源(人力和时间)。理想情况下,管理员和支持工程师希望一次性将更新的文件部署到中央服务器,然后让更新的文件自动复制到每个桌面安装。SmartAssembly
就是这样一种解决方案,它使用“拉取模型”来实现 .NET 应用程序的更新。
.NET 框架已经为“智能客户端”应用程序提供了支持。您可以在配置文件中配置 <DEPENDENTASSEMBLY>
节点(详情请参阅 MSDN),让运行时下载关联的程序集。但是,存在一些缺点
- 配置过于简单,缺乏灵活性。
- 下载过程是一个“黑盒”,对终端用户不友好。
- 在后期绑定情况下,如果通过其弱名称(未指定版本、公钥和区域性)加载程序集,运行时将在每次加载同一程序集时打开 HTTP 连接来检查远程程序集。当然,如果您需要频繁加载一些程序集,这将浪费大量时间。
此外,微软还发布了一个名为 Updater 的应用程序块,它也提供了一个“拉取模型”解决方案,用于从中央位置自动下载应用程序更新。但它不是即时工作的。相反,它频繁检查远程清单文件以确定是否需要更新。如果需要,它会启动一个 Updater 进程并关闭用户应用程序以下载更改的文件。下载所有更改的文件后,它会再次启动用户应用程序。
SmartAssembly
旨在满足以下要求
- 使下载进度可控、可见和可定制。
- 支持断点续传。
- 提供支持压缩文件的框架。
- 简化部署者的配置工作。
- 为部署者提供配置系统的灵活性。
- 为开发人员提供可定制性和可扩展性。
工作原理
类 AppDomain
和 Assembly
中定义了一组 Resolve
事件。这些事件为开发人员提供了自行解析程序集、资源和模块的机会。SmartAssembly
只使用 AssemblyResolve
事件。当该事件触发时,SmartAssembly
搜索配置以查找关联的 codebase URI,然后根据 URI 下载程序集并将其保存到本地,最后加载程序集并将其返回给 AppDomain
。
使用 SmartAssembly
使用 SmartAssembly
分为两个部分进行描述。首先,需要在应用程序中添加一段代码。然后,编写配置文件并部署应用程序。
编码
顺便说一句,源代码包中附带一个 CHM 文件。您可以参考它了解如何使用 SmartAssembly
的详细信息。
1. 创建 SmartAssemblyManager 实例
类 SmartAssemblyConfig
用于从 SmartAssembly
配置节创建 SmartAssemblyManager
实例。有三种方法可以实现。
- 从应用程序配置文件加载。通过这种方式,返回的
SmartAssemblyManager
实例也是SmartAssemblyManager.CurrentManager
,并且其CurrentDomain
属性已经设置为AppDomain.CurrentDomain
。相比之下,其他两种方式只是创建一个新的SmartAssemblyManager
实例SmartAssemblyManager sam = ConfigurationSettings.GetConfig(Lightning.SmartAssemblyConfig.SectionName) as SmartAssemblyManager;
- 从
SmartAssembly
的独立配置文件加载SmartAssemblyManager sam = SmartAssemblyConfig.Create("c:\test.xml");
- 从准备好的配置
XmlNode
加载// Prepare the configuration XmlNode XmlNode section = ...; SmartAssemblyManager sam = SmartAssemblyConfig.Create(section); if( null != sam ) { sam.CurrentDomain = AppDomain.CurrentDomain; }
2. 启用 SmartAssembly
要启用 SmartAssembly
,您需要将 SmartAssemblyManager
实例的 CurrentDomain
属性设置为 AppDomain
。
if( null != sam ) {
sam.CurrentDomain = AppDomain.CurrentDomain;
}
如上所述,如果您从应用程序配置文件创建 SmartAssemblyManager
实例,并且只想处理 AppDomain.CurrentDomain
,则可以跳过此步骤。
3. 自定义下载 SmartAssembly 配置文件的例程
SmartAssembly
配置文件可以是独立文件,甚至是数据库记录,因此您可以下载它或从数据库中获取它。SmartAssemblyConfig
提供了一个 static
委托供您执行此操作。
Public static DownloadConfigDelegate DownloadConfigCallback;
4. 自定义解压缩文件的例程
SmartAssembly
在此版本中不提供该功能。但是,它提供了一个定义完善的框架来简化您的工作。您所需要做的就是开发一个 ExtractFileInZipDelegate
函数并处理 SmartAssemblyManager
实例的以下委托,然后遵循压缩文件的配置规则(详见部署部分)。
public ExtractFileInZipDelegate ExtractFileInZipCallback;
5. 自定义其他例程
SmartAssembly
还为 LoadAssembly
、LoadlocalAssembly
、DownloadFile
等提供了可定制性。
public event LoadAssemblyEventHandler CustomLoadAssembly;
public event LoadAssemblyEventHandler CustomLoadlocalAssembly;
public event SmartAssemblyEventHandler CustomDownloadFile;
public event SmartAssemblyEventHandler CustomDownloadCompleted;
public event DownloadProgressEventHandler CustomDownloading;
public event SmartAssemblyCancelEventHandler BeforeDownload;
public event SmartAssemblyEventHandler AfterDownload;
部署
部署工作主要集中在如何编写配置文件。本节将详细介绍如何配置 SmartAssembly
。
1. smartAssemblyConfiguration
这是配置的根节点。
<a href="#node_sac"><smartAssemblyConfiguration></a>
<a href="#node_sc"><smartConfig></a>
<a href="#node_cd"><cacheDirectory></a>
<a href="#node_ns"><netSetting></a>
<a href="#node_ll"><loadLogic></a>
<a href="#node_da"><dependentAssembly></a>
<a href="#node_ai"><assemblyIdentity></a>
<a href="#node_cb"><codeBase></a>
<a href="#node_br"><bindingRedirect></a>
子元素 | 描述 | 必需 |
<smartConfig> | 指定智能配置文件的设置。 | N |
<cacheDirectory> | 指定缓存目录的设置。 | Y |
<netSetting> | 指定网络连接的参数。 | N |
<loadLogic> | 指定加载程序集的逻辑。 | N |
<dependentAssembly> | 封装每个程序集的绑定策略和程序集位置。 | N |
2. smartConfig
配置独立的 SmartAssembly
配置文件。如果此节点存在,SmartAssembly
将尝试从该设置加载配置,其他节点将被忽略。
<a href="#node_sac"><smartAssemblyConfiguration></a>
<a href="#node_sc"><smartConfig></a>
Attribute | 描述 | 必需 | 默认值 |
href | 指定 SmartAssembly 可以找到配置文件的 URL。 | N | |
filePath | 指定 SmartAssembly 保存配置文件的完整文件路径。 | N | |
tryLocal | 如果下载远程文件失败,则尝试本地文件。 | N | true |
3. cacheDirectory
本地缓存目录的设置。
<a href="#node_sac"><smartAssemblyConfiguration></a>
<a href="#node_cd"><cacheDirectory></a>
Attribute | 描述 | 必需 | 默认值 |
路径 | 指定 SmartAssembly 存储程序集的缓存路径。 | Y | |
type | 指定缓存路径的类型。(枚举 :KeepNewestOnly 、KeepAllVersions 、KeepAllByHashCode ) | N | KeepNewestOnly |
packageFilePath | 指定 SmartAssembly 存储压缩文件的缓存路径。 | N | |
shadowCopyCachePath | 指定 ShadowCopy 的缓存目录。 | N | |
shadowCopyExtraDirs | 指定 ShadowCopy 的额外目录。 | N |
4. netSetting
网络参数的设置。
<a href="#node_sac"><smartAssemblyConfiguration></a>
<a href="#node_ns"><netSetting></a>
Attribute | 描述 | 必需 | 默认值 |
agentName | 指定 HttpRequest 的代理名称。 | N | |
bufferSize | 指定下载缓冲区的大小。 | N | 4096 |
timeout | 指定 HttpRequest 的超时值。 | N | -1 |
5. loadLogic
加载程序集的逻辑。
<smartAssemblyConfiguration>
<loadLogic>
Attribute | 描述 | 必需 | 默认值 |
notCheckRemoteWhileMatched | 指定即使本地文件与请求完全匹配,是否也检查远程文件(程序集)。 | N | true |
downloadNewerOnly | 指定是否仅在远程文件比本地文件更新时才进行下载。 | N | false |
tryLatestVersionWhileNotMatch | 指定是否自动使用配置文件中配置的最高版本。 | N | true |
smartMatch | 指定是否使用“智能匹配”技术。 | N | true |
loadSymbols | 指定是否尝试下载与要解析的程序集关联的符号文件。 | N | false |
symbolsFileExtName | 指定将用于计算 URI 的符号文件的扩展名。 | N | pdb |
loadMethod | 指定加载程序集的方法。(枚举 :Directly 、ViaMemoryStream 、ShadowCopy ) | N | Directly |
identifiedByName | 指定是否使用弱名称来标识程序集。 | N | false |
workOffline | 指定是否在离线模式下工作。 | N | false |
baseHref | 指定基本 URI,它将用于计算程序集的 URI。 | N | |
defaultZipFile | 指定默认的压缩文件名,它将用于计算尚未配置的程序集的 URI。 | N |
6. dependentAssembly
封装每个程序集的绑定策略和程序集位置。每个程序集使用一个 <dependentAssembly>
元素。
<a href="#node_sac"><smartAssemblyConfiguration></a>
<a href="#node_da"><dependentAssembly></a>
<a href="#node_ai"><assemblyIdentity></a>
<a href="#node_cb"><codeBase></a>
<a href="#node_br"><bindingRedirect></a>
子元素 | 描述 | 必需 |
<assemblyIdentity> | 包含有关程序集的标识信息。此元素必须包含在每个 <dependentAssembly> 元素中。 | Y |
<codeBase> | 如果共享程序集未安装在计算机上,则指定运行时在哪里可以找到它。 | N |
<bindingRedirect> | 将一个程序集版本重定向到另一个版本,甚至重定向到另一个程序集。 | N |
6.1. assemblyIdentity
包含有关程序集的标识信息。
<a href="#node_sac"><smartAssemblyConfiguration></a>
<a href="#node_da"><dependentAssembly></a>
<a href="#node_ai"><assemblyIdentity></a>
Attribute | 描述 | 必需 | 默认值 |
名称 | 程序集的名称。 | Y | |
publicKeyToken | 一个十六进制值,指定程序集的强名称。 | N | |
文化 | 一个字符串,指定程序集的语言和国家/地区。 | N | |
notCheckRemoteWhileMatched | N | true |
6.2. codeBase
指定公共语言运行时在哪里可以找到程序集。
<a href="#node_sac"><smartAssemblyConfiguration></a>
<a href="#node_da"><dependentAssembly></a>
<a href="#node_cb"><codeBase></a>
Attribute | 描述 | 必需 | 默认值 |
version | 指定代码库适用的程序集版本。程序集版本号的格式为 major.minor.build.revision 。版本号每个部分的有效值为 0 到 65535 | N | |
href | 指定运行时可以找到指定版本程序集的 URL。 | N |
6.3. bindingRedirect
将一个程序集版本重定向到另一个版本,甚至重定向到另一个程序集。
<a href="#node_sac"><smartAssemblyConfiguration></a>
<a href="#node_da"><dependentAssembly></a>
<a href="#node_br"><bindingRedirect></a>
Attribute | 描述 | 必需 | 默认值 |
oldVersion | 指定最初请求的程序集版本。有三种可能的格式
| N | |
newVersion | 指定要使用的程序集版本或新程序集,而不是最初请求的版本。新程序集的格式应如下所示 NewAsm, Version=1.0.0.0, Culture=en-us, PublicKeyToken= | N |
一个完整的例子
<configuration>
<!-- Declaring custom config section parsing class -->
<configSections>
<section name="smartAssemblyConfiguration"
type="Lightning.SmartAssemblyConfig, SmartAssembly"/>
</configSections>
<smartAssemblyConfiguration>
<!--smartConfig temp="%ComAppData%\Assembly\config.xml"
href="https:///Assembly/Test.xml" /-->
<cacheDirectory path="%ComAppData%\Assembly\Origin"
type="KeepAllVersions"
packageFilePath="%ComAppData%\Assembly\ZipFiles" />
<netSetting agentName="Smart Assemlbly Manager"
bufferSize="8182" timeout="-1"
proxyMode="" />
<loadLogic notCheckRemoteWhileMatched="true"
downloadNewerOnly="true"
tryLatestVersionWhileNotMatch="true"
smartMatch="true"
loadSymbols="true"
loadMethod="ShadowCopy"
identifiedByName="true"
workOffline="false"
baseHref="https:///Assembly/" />
<dependentAssembly>
<assemblyIdentity name="MainControl" publicKeyToken="" culture="" />
<codeBase version="" href="old/MainControl.dll"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="SubControl1"
publicKeyToken="a9061ec0e85bbecf"
culture="" />
<codeBase version="0.0.1.0" href="old/SubControl1.dll"/>
<codeBase version="2.1.0.0" href="new/SubControl1.dll"/>
<bindingRedirect oldVersion="0.0.0.1; 0.0.0.2" newVersion="0.0.1.0" />
<bindingRedirect oldVersion="1.0.*" newVersion="2.1.0.0" />
<bindingRedirect oldVersion="1.1.0.0 - 2.0.0.0" newVersion="2.1.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="SubControl2" publicKeyToken="" culture="" />
<codeBase version="" href="old/SubControl2.dll"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="MainControl.resource" publicKeyToken="" culture="" />
<bindingRedirect oldVersion="*"
newVersion="MainControl.resource, Version=, Culture=, PublicKeyToken=" />
</dependentAssembly>
</smartAssemblyConfiguration>
</configuration>
关于演示
演示解决方案中有三个项目
SmartAssembly | SmartAssembly 库。 |
测试 | 可以独立执行或由 IE 加载的演示应用程序(详见 readme.txt)。 |
TestControl | 将被“SmartAssembly”的演示程序集。 |
关注点
部署有一些技巧,例如
- 决定将缓存目录设置到何处,是
AppBaseDir
、AppData
还是ComAppData
。 - 如果使用压缩文件,如何打包程序集,作为应用程序、作为包还是其他策略?
许可证
本文未附加明确的许可证,但可能在文章文本或下载文件本身中包含使用条款。如有疑问,请通过下面的讨论区联系作者。
作者可能使用的许可证列表可以在此处找到。