Chris SellsMicrosoft Corporation
2003 年 5 月 23 日
摘要:Chris Sells 共享某些自定义代码,您可以将其用在客户端和服务器端中以创建自动部署 Windows 窗体应用程序。(本文还包含英文链接。请注意,在示例文件中,程序员的注释使用的是英文,本文中将其译为中文是为了便于读者理解。)
下载 winforms05152003.exe 示例文件。
我最容易被问及的问题之一是在人们开始使用“自动部署 (NTD) 应用程序”时,即可以用 URL 启动的 Windows 窗体应用程序,如何将命令行参数传递给这些程序。很明显,用户想要在其 Web 页面上提供不同启动选项的链接,或者想要基于当前用户的会话,用命令行参数动态生成 URL。有关后者的示例,请仔细查看图 1。
图 1. 带有指向 NTD 应用程序的链接的 Web 页面
图 1 显示了一个 Web 页面,它明显地针对访问的用户进行了个性化。在 Web 页面上的链接指向一个 NTD 应用程序,该应用程序在第一次运行时类似于图 2。
图 2. NTD 应用程序登录窗体
注意,此应用程序启动时预填充了用户名和 ID。我执行此操作的方法是使用如下格式的 URL 传递参数:http://localhost/vacaplan/vacaplan.exe?uid=csells&uname=Chris Sells
从本地硬盘驱动器中启动被管理的应用程序时,命令行参数可以从传递到 Main 的字符串数组中获得:
static void Main( string [] args) { // 获得命令行参数 string uid = ""; string uname = ""; foreach( string arg in args ) { string[] pair = arg.Split('='); switch( pair[0].ToLower() ) { case "uid": uid = pair[1]; break; case "uname": uname = pair[1]; break; } } }遗憾的是,支持从启动 URL 拖出命令行参数对于 Microsoft .NET Framework 1.1 来说是全新的并且几乎没有说明。而且,因为启动 URL 被用来创建指向 .config 文件的路径,所以对命令行参数的完全支持还需要在服务器端上运行某些代码。
注意:在 NET 1.0 中可以使用一种替代方法将命令行参数拖出启动 URL,本文稍后将对其进行介绍。要将参数拖出启动 URL,首先需要从 NTD 应用程序内部访问启动 URL。为此,.NET 1.1 提供了来自应用程序域的 APP_LAUNCH_URL 数据变量:
// 仅可用于 .NET 1.1+ AppDomain domain = AppDomain.CurrentDomain; object obj = domain.GetData( " APP_LAUNCH_URL " ); string appLaunchUrl = (obj != null ? obj.ToString() : "" );MessageBox.Show(appLaunchUrl);从 APP_LAUNCH_URL 中可以提供完整的用来启动 NTD 应用程序(包括参数)的 URL。遗憾的是,APP_LAUNCH_URL 在 .NET 1.0 中不可用。但是,因为指向 NTD 应用程序的 .config 文件的路径就是将“.config”加在最后的 URL(包括参数),因此您可以在 .NET 1.0 中拖出与 APP_LAUNCH_URL 等效的参数。例如,从以下位置启动应用程序:
http://foo/foo.exe?foo=bar@quux将产生以下 .config 文件路径:
http://foo/foo.exe?foo=bar@quux.config因为应用程序域提供对 .config 文件路径的访问权限,所以对于 .NET 1.0 和 .NET 1.1 来说,您都可以使用此权限和少量字符串操纵获得对 NTD 启动 URL 的访问:
// 仅可用于 .NET 1.1+ AppDomain domain = AppDomain.CurrentDomain; object obj = domain.GetData( " APP_LAUNCH_URL " ); string appLaunchUrl = (obj != null ? obj.ToString() : "" ); // 回到 .NET 1.0 if ( appLaunchUrl == string .Empty ) { const string ext = ".config"; string configFile = domain.SetupInformation.ConfigurationFile; appLaunchUrl = configFile.Substring(0, configFile.Length - ext.Length);}无论哪种方法,针对 .NET 1.x 的默认 Intranet 和 Internet访问权限都允许从被部分信任的客户端访问命令行参数信息。一旦您获得了完整的 URL,就可以用它来对参数进行解码和分析参数。
在了解如何获得参数之前,我必须简要说明有关在 NTD 应用程序中处理命令行参数的安全性含义。当参数被传递到已经安装在计算机中的 EXE 时,此操作通过 shell 或命令行控制台完成,因此您可以信任此操作。但是,在 Web 上,用户随时会受骗打开电子邮件附件或在浏览器中单击对其不利的链接。例如,将 HotMail 设想为允许下列参数的 NTD:
http://hotmail.com/edit.exe?uid=csells&forward=doctor@evil.com&ui=no在这种情况下,没有任何确认 UI,我们就将指定转发电子邮件意图的参数传递给了其他人。如果此链接被嵌入到 Web 页面中并标为“Free Chocolate!”,老实说您能不受诱惑自己不去单击此链接?在将参数发送到不受控制的、混乱的 Web 世界之前,请确保已仔细考虑命令行参数组合暴露的可能性并提防那些居心不良的人。
可以控制安全性以后,您将需要分析 URL 本身的参数。有时您需要将特殊字符编码到传送这些字符的 URL 中,就象您将这些字符传递到服务器端的一段代码一样。例如,要对 uname 参数中的空格进行编码,需要用