.net framework 中的无接触部署
2002年7月
摘要:本文介绍一个激动人心的新功能,即使用 web 服务器简化 windows 窗体智能客户端的部署和更新。本文引用的任务管理示例应用程序可以从 visual basic .net 中找到。 单击此处打开或复制“无接触部署”项目文件。(请注意,在示例文件中,程序员的注释使用的是英文,本文中将其译为中文是为了便于读者进行理解。)
目录
- 简介
- 使用 web 服务器的无接触部署
- 示例演示
- 提高 windows 窗体响应速度
- 安全性
- 使用多程序集应用程序的无接触部署
- 无接触部署和 xml web service
- 可选:如何设置安全策略
- 客户端要求
- 小结
简介
您是否曾经必须部署 visual basic 客户端服务器应用程序?或者曾经必须部署依赖于 com 注册的 win32 应用程序?企业桌面环境中的正确安装一直受到各种问题的困扰,这其中既有试图使所有用户升级这样的简单问题,也有较为复杂的 dll 版本控制问题。
与 web 应用程序相比,桌面应用程序有很多优点,具体表现在以下几个方面:
- 丰富的用户界面 (ui)
- 较快的响应速度
- 较好的性能
- 能够脱机运行
- 可以有效地使用边缘资源(客户机)
- 易于同本地应用程序和 api 集成
尽管桌面应用程序具有以上优点,但由于 web 应用程序使应用程序的部署和更新相对容易,因此在过去几年中得到了广泛的应用。
microsoft 准备通过 .net framework 将 web 应用程序在部署和维护方面的所有优点都集成到桌面应用程序中。dll 版本控制问题也得到了解决 – 在默认情况下,使用 .net framework 生成的应用程序彼此完全孤立,并从各自的专用应用程序目录中检索其 dll。dll 仍然可以在多个应用程序之间共享,但这并非使用系统注册表实现,而是将共享的 dll 存储在 .net framework 全局程序集缓存中,该程序集缓存可加载给定 dll 的多个版本并跟踪版本与应用程序之间的匹配关系。在实际部署应用程序的过程中,.net framework 允许系统管理员按照部署和更新 web 应用程序(通过远程 web 服务器)的方式部署应用程序和应用程序更新。此项技术称为无接触部署,是本文要论述的中心内容。
使用 web 服务器的无接触部署
使用无接触部署,可以下载、安装和直接在用户计算机上运行 windows 窗体应用程序(使用 .net framework 的 windows 窗体类生成的桌面应用程序),而无须改变注册表或共享的系统组件。
工作原理
.net framework 安装提供了一个挂接 internet explorer 5.01 和更高版本以侦听所请求的 .net 程序集的机制。在请求期间,可执行程序被下载到磁盘上称为程序集下载缓存的位置。然后,名为 ieexec 的进程在具有有限安全设置的环境中启动该应用程序。
图 1:无接触部署方案
示例演示
这是一个非常简单的 windows 窗体应用程序,用户可以使用它管理任务列表。这些任务可用于错误跟踪、it 疑难解答,也可用于任务列表(该列表与 outlook xp 或 visual studio .net 中的列表相似)。
首先,在 visual studio .net 中打开此应用程序。任务管理应用程序是在 visual basic .net 中使用 windows 窗体和名为 taskmgmtws 的 xml web service(它使用 ado.net 与 access 数据库通信以存储任务)实现的。
任务管理应用程序使用 taskmgmtws web 服务更新 datagrid windows 控件。应用程序首先实例化一个名为 ws 的 xml web service 对象。接着调用 web 方法 gettasks(),获取任务的 ado.net 数据集。然后将任务数据集分配给 datagrid windows 控件中的 datasource 属性。
调用 web 服务。 dim ws as localhost.service1 = new localhost.service1() dim ds as dataset = ws.gettasks() 将生成的数据集绑定到 datagrid 控件。 datagrid1.datasource = ds datagrid1.datamember = "tasks"
应用程序返回时,datagrid 被更新,应用程序也将更新。此时,我们遇到了在基于网络的应用程序中常见的问题。第一次加载期间,应用程序将生成一个网络调用,可能需要几秒钟才能完成。
提高 windows 窗体响应速度
要提高应用程序的总体响应速度,可以利用后台线程。已更新的应用程序首先调用辅助线程来实例化一个 xml web service 对象。web 服务实例化后,我们将使用 methodinoker() 来安全地更新 ui。
从 form load 事件中的辅助线程开始:
使用后台辅助线程生成 web 服务调用, 以提高第一次窗体加载过程中应用程序 的总体响应速度。 threadpool.queueuserworkitem(new waitcallback
(addressof gettaskswebservicebackground))
有关如何在后台线程中更新 windows 窗体的详细信息,请访问知识库文章 q318604“populate datagrid on background thread with data binding by using visual basic .net”,网址为 http://support.microsoft.com/default.aspx?scid=kb;en-us;q318604。
在 windows 窗体运行的同时,编写一个作用于 xml web service 调用的后台线程。
private sub gettaskswebservicebackground(byval data as object) 调用 web 服务。 dim ws as localhost.service1 = new localhost.service1() m_ds = ws.gettasks() 更新 windows 窗体数据网格。 dim mi as new methodinvoker(addressof updatedatagridform) dim ia as iasyncresult = begininvoke(mi) cursor = cursors.default end sub
为了说明如何将应用程序部署到 web 服务器上,我们将任务管理应用程序部署到 tasks web service web 文件夹中。首先将生成文件夹更改为 taskmgmtws web service iis 虚拟目录。方法是打开“taskmanagement property pages”(taskmanagement 属性页)对话框,然后将输出路径设置为“..\taskmgmtws\”。
将生成结果路径设置为 web 服务器后,可以通过简单的重新编译来部署此应用程序。应用程序生成后,我们可打开 internet explorer 并浏览到应用程序 http://localhost/taskmgmtws/taskmanagement.exe。请注意,安装了 .net framework 的 internet explorer 不会要求您保存该应用程序,而是尝试运行该程序。如果要从 web 页下载应用程序,可以使用“file://”协议处理程序。
应用程序现已通过 http 下载并安装到程序集下载缓存中。运行该应用程序之前,将检查安全策略以确保应用程序拥有执行其操作的权限。
上面介绍了如何通过 web 服务器运行该应用程序,下面就让我们更改该应用程序,看看对它进行升级有多么容易。选择 datagrid,可以使用 auto format(自动套用格式)属性快速更改背景样式。
然后重新生成应用程序,以更新 web 服务器上的 .exe 文件。最妙的是当用户请求返回到 windows 窗体时,应用程序代码将自动更新。.net framework 将自动检查程序集的时间戳,查看是需要再次下载该程序集,还是只需通过用户的程序集下载缓存来运行该程序集。
安全性
代码访问安全性是保护桌面免受正在通过无接触部署方式下载的 windows 窗体应用程序影响的关键。此模型通过匹配应用程序和应该分配给应用程序的权限来工作。在运行时,公共语言运行时从程序集中收集凭证。凭证可以采用代码源自的 internet explorer 区域(本地磁盘、intranet、internet、受信任站点或不受信任站点)的形式,也可采用代码源自的 url(签名使用的私钥、哈希值、authenticode 发布服务器签名等等)的形式。使用此凭证,公共语言运行时将程序集分配给相应的代码组或类别。每个代码组都拥有分配给它的权限集,说明程序集应获得的权限,例如能否读取或写入本地磁盘、访问联网资源、打印以及访问环境变量等等。
默认情况下,.net framework 附带围绕 internet explorer 区域设置的代码组。例如,来自 intranet 区域的代码获得的权限很有限,因此无法执行文件 io 访问。
为了说明安全检查在起作用,任务管理可执行程序包含一个名为 read boot.ini 的工具栏按钮,该按钮尝试访问 c:\ 盘中的文件。
您可以进行一个简单的测试,单击“read boot.ini”按钮,查看当应用程序请求 c:\ 根目录中的文件时会发生什么情况 – 引发安全异常,应用程序不处理该请求。
异常返回一个文件 io 权限异常,说明应用程序无法访问 taskmanagement.exe 请求的特定资源。
使用多程序集应用程序的无接触部署
在本示例应用程序中,我们已经说明了如何加载单个程序集。通过对 assemble 对象使用 loadfrom() 方法,.net framework 还可以有效地将多程序集应用程序传入客户端。
assemble 类具有 loadfrom 方法,可以初始化一个对特定程序集的引用。loadfrom 的参数是 url 或文件路径名。指定 url 后,.net framework 首先通过检查程序集下载缓存,检查客户端是否存在已命名的程序集。如果程序集不在程序集下载缓存中,.net framework 将从 web 服务器获取该程序集,并将它的副本置于下载缓存中。这样,程序集对象即可在代码中使用。
例如,如果在一个单独的名为 aboutform.dll 的程序集中实现了 taskmanagement about windows 窗体,则可以在用户请求查看“about”(关于)对话框时使用 loadfrom 下载该程序集。这样,当用户与应用程序交互时,我们只需传输应用程序所需的代码。
无接触部署和 xml web service
一个重要的安全限制是,当通过 web 服务器分发应用程序时,其域必须与它所依赖的所有 web 服务相匹配。例如,如果从 http://myserver/taskmanagement.exe 启动 taskmanagement.exe,则只允许使用 http://myserver 上的 xml web service。出于安全性方面的考虑,不允许应用程序从其他服务器调用 web 服务。
可选:如何设置安全策略
计算机管理员可以更改安全权限,以便将更多权限授予现有代码组或从头开始创建新代码组。
继续操作之前,必须明白更改安全设置是很危险的,因此切勿将其关闭。强烈建议,在任何情况下都只更改能使应用程序运行的安全设置。
为此,如果您是计算机管理员,则可以运行 caspol 命令行工具(位于 %systemroot%\microsoft.net\framework\v1.0.3705\caspol.exe),为从本地主机启动的应用程序授予对本地磁盘的完全访问权限:
caspol -machine -addgroup all_code -url http://localhost/* fulltrust -n taskmanagement
现在,由于此应用程序具有执行文件 io 的权限,因此能够返回 boot.ini 的内容。
除了 caspol 命令行工具以外,还通过 microsoft 管理控制台 (mmc) 管理单元提供了图形配置工具,即 .net framework 配置工具。打开管理单元后,打开“my computer”(我的电脑),单击“runtime security policy”(运行时安全策略),然后依次单击“machine”(计算机)、“code groups”(代码组)和“all_code”(所有代码),浏览到 taskmanagement。使用 taskmanagement 可以查看新建的代码组。尝试设置新代码组,了解由代码访问安全设置所带来的灵活性和把握度。
确保查看各选项后删除在上文中创建的代码组。可以通过运行以下命令完成此操作:
caspol -remgroup taskmanagement
也可通过 mmc 工具在 taskmanagement 上单击右键并选择 delete(删除)来删除新代码组,该工具使您能够轻松地在代码组之外生成 msi 文件,如果需要,可以使用系统管理服务器或组策略在企业中传播该文件。
客户端要求
- 任何支持 .net framework 的操作系统
- 已安装 sp1 的 .net framework
- internet explorer 5.0.1 或更高版本
- 访问 iis web 服务器进行应用程序部署
小结
无接触部署为分发 window 窗体应用程序提供了非常好的方法。应用程序开发人员可以利用这一强大的桌面处理能力,同时保持由 web 应用程序实现的部署和维护的优点。
有关详细信息,请访问
- windows 窗体社区站点(英文)
- death of the browser?
- windows forms deployment
- windows forms security
- 有关如何更好地扩展到无接触部署的信息,请访问 .net application updater componenth
