.NET中ClickOnce /智能客户端部署的陷阱/陷阱
我准备将几个.NET Windows Forms应用程序转换为ClickOnce / smart-client部署方案。我已经读过《不是这个伟大的教程》,但是我应该注意一些陷阱或者"陷阱"吗?
有几个次要的应用程序经常使用,但主要的应用程序是C#,运行24/7,相当大,但是每隔几周才更改一次。它还在本地写入日志文件,并与本地硬件设备对话。
解决方案
这是我所知道的一些。
- 无法在桌面上放置图标。你现在可以。
- 我不能为所有用户安装。
- 我需要跳过箍才能将部署移动到其他服务器。如果我们在内部进行开发,并且用户可以看到我们要发布到的服务器,或者我们正在部署到公共Web上,这不是问题,但是如果我们需要独立地扩展到多个客户站点,那不是很好。
- 从.NET 3.5 SP1开始,我们不再需要对部署清单进行签名,这使将部署移至新服务器变得更加容易。
- 我无法在GAC中安装程序集。我们可以通过创建常规安装程序包来解决此问题,这些程序包是ClickOnce应用程序的准备工作。
ClickOnce的陷阱之一是我们无法安装到GAC。如果要安装共享DLL文件的多个应用程序,这将是一个问题。每个应用程序都将需要DLL文件的本地副本。同样,多个用户的安装也已完成。请参阅将Window Installer与ClickOnce进行比较的列表。
我们有一个应用程序要部署为ClickOnce应用程序。我们需要用户能够修改安装中的某些设置(例如IT希望从其网络共享中提供文件的部署路径,在构建时未知)。更改部署中的任何文件时,我们需要重新计算所有哈希值,并对所有内容重新签名。因此,如果此解决方案是内部的,则传递签名证书的过程可能不会有问题,但是,如果这是针对客户的,则我们将需要设计一个不错的解决方案来绕过此问题。
我从互联网上的某个地方听到谣言,说将来版本的ClickOnce可以消除一些麻烦。
ClickOnce应用程序无法做很多事情,例如在用户桌面上安装快捷方式或者在应用程序的安装位置有任何sayo。对于某些人来说,这些都是破坏交易的因素。
自从我使用它已经有一段时间了,但是我们可以使用一种特殊的方式来找出并显示ClickOnce版本/内部版本号,该版本与应用程序的版本/内部版本号是分开的。我们必须执行一次try / catch,如果ClickOnce版本/内部版本号引发异常,则该应用程序将不会作为由ClickOnce部署的应用程序运行(也就是说,它作为常规编译的应用程序运行,或者从Visual Studio运行)。
对于一个简单的应用程序(即不是Microsoft Word,而是一个快速而肮脏的应用程序),它需要大量的常规部署,因此ClickOnce很棒。但是,我们很快就会碰到"哦,ClickOnce无法完成此操作,请选择MSI或者其他方法)。
我们将比普通的.NET应用程序具有更少的系统访问权限。
那是因为我们将获得较低的信任度。 《 .NET Framework开发人员指南:ClickOnce部署和安全性》中的更多信息。
我最大的问题是,无法使用机器密钥来加密配置文件的各个部分,因为我们无权访问该密钥(考虑到它,保护该密钥很有意义)。
大多数问题已得到解决,但是有几个人提到无法创建桌面快捷方式。实际上,我们可以使用VisualStudio2008 SP1创建桌面快捷方式。
另外,如果我们没有使用最新版本的Visual Studio,则始终可以编写代码来创建已安装的开始菜单快捷方式的快捷方式。
如果有人在搜索中提及此问题,我们发现许多客户担心缺乏"分发"其应用程序的安全性。该应用程序必须在公共场所可用且未经任何身份验证,才能检查更新。唯一的例外是我们具有Windows NT身份验证。我认为保护ClickOnce应用程序安全可以解释我的意思。
桌面图标通过代码非常简单,而且如上所述,使用3.5 SP1时,它已经成为问题。
xmlSerializer仍然存在未修复的错误,在某些情况下无法正确部署。一个简单的解决方法是手动将此文件添加到部署中。 PITA,但它很容易...但是,当部署突然失败时,可能会令人震惊...
- 部署更新后,内置对话框将使它看起来像重新下载整个应用程序一样。实际上,仅下载了已更改的DLL,并且显示的进度条是误导性的/错误的。不要浪费时间试图弄清楚为什么要重新部署所有程序集,只是发现它们实际上不是。不是说我那样做或者做任何事。
- 当我们用来签署原始部署清单的证书过期并被签发新证书时,我们将蒙受巨大的痛苦(客户端都需要卸载并重新安装)。详细信息在马口中。
我们不能以静默方式卸载ClickOnce部署的应用程序。另外,我认为不可能在启动快捷方式中添加参数。
我不知道SP1允许我们创建桌面图标。这是我们一直在做的事情(现在称为"困难的方式"):
try { string company = string.Empty; string product = string.Empty; if (Attribute.IsDefined(asm, typeof(AssemblyCompanyAttribute))) { AssemblyCompanyAttribute asCompany = (AssemblyCompanyAttribute)Attribute.GetCustomAttribute(asm, typeof(AssemblyCompanyAttribute)); company = asCompany.Company; } if (Attribute.IsDefined(asm, typeof(AssemblyProductAttribute))) { AssemblyProductAttribute asProduct = (AssemblyProductAttribute)Attribute.GetCustomAttribute(asm, typeof(AssemblyProductAttribute)); product = asProduct.Product; } if (!string.IsNullOrEmpty(company) && !string.IsNullOrEmpty(product)) { string desktopPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), product + ".appref-ms"); string shortcutPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Programs), Path.Combine(company, product + ".appref-ms")); File.Copy(shortcutPath, desktopPath, true); } } catch { // Shortcut could not be created }
如果客户端位于需要身份验证的代理之后,则无法安装。