我应该如何实现自动更新?
许多程序都包含一个自动更新程序,程序偶尔会在线查看更新,然后下载并应用所发现的任何更新。 程序错误是固定的,支持文件被修改,事情(通常)做得更好。
不幸的是,无论我看起来多么困难,我无法在任何地方find关于这个过程的信息。 似乎已经实施的自动更新程序要么是专有的,要么不被认为是重要的。
看起来networking上的更新的系统似乎很容易实现,如果可用,下载它们。 自动更新程序的这一部分将在实现过程中发生重大变化。 问题是应用补丁有哪些不同的方法。 只需下载文件并用新文件replace旧文件,运行下载的迁移脚本,系统的猴子补丁部分等等。 概念是首选,但在Java,C,Python,Ruby,Lisp等的例子将不胜感激。
我认为“语言不可知论”将成为一个限制因素。 应用程序的形状和大小如此之多以至于没有一个通用的答案。 我用几种语言实现了几个自动更新程序,没有两个是类似的。
最普遍的理念是,应用程序检查某个家庭位置(url,networking查询,企业networking位置等),询问它是最新版本还是询问最新版本。 如果答案要求更新,那么每个情况下的过程都会有所不同。
stream行的替代方法是在启动应用程序时邀请家庭地点运行脚本。 例如,脚本可以检查版本,必要时下载更新,并要求使用反馈。
如果缩小参数,我们可能会帮助更好。
更新:“修补”的方法也取决于应用程序的性质,这里有一个非常广泛的多样性。 例如,如果您有一个可执行文件,那么replace可执行文件可能是最实际的。 如果您的应用程序有很多文件,您应该寻找方法来最大限度地减lessreplace文件的数量。 如果您的应用程序是高度自定义的或参数化的,您应该尽量减less重新定制的工作量。 如果您的应用程序采用了解释代码(如Excel VBA应用程序或MS Access MDB应用程序),那么您可能可以replace部分代码。 在Java应用程序中,您可能只需要replaceJAR文件,甚至是JAR内容的子集。 您还需要有一种方法来识别当前的客户端版本,并进行适当的更新。 我可以继续下去,但是我希望你看到我关于多样性的观点。 这是最好的答案通常是以“好的,这取决于…!”开始的许多次之一。 这就是为什么这么多的答案包括“请缩小参数”。
一定要考虑吸收关于更新的信息以及更新二进制文件本身的安全含义。
你相信下载的来源? 你可能打电话到家里得到你的更新,但是如果中间有一个人redirect到恶意服务器呢。 HTTPS或类似的安全连接将有所帮助,但build议您再次使用数字签名检查来检查您最终下载的位。
首先,您需要在您的应用程序主页上使用最新版本的文件。 我认为这个任务有特殊的SQL表的最好的方法,并在发布新版本/ nightly构build完成后自动填充它。 你的应用程序创build一个新的线程,请求与版本内置的http链接,并与当前的比较。 在.NET中使用可以使用这样的代码:
Version GetLatestVersion() { HttpWebRequestrequest = (HttpWebRequest)WebRequest.Create(new Uri(new Uri(http://example.net), "version.txt)); HttpWebResponse response = (HttpWebResponse)request.GetResponse(); if (request.HaveResponse) { StreamReader stream = new StreamReader(response.GetResponseStream(), Encoding.Default); return new Version(stream.ReadLine()); } else { return null; } } Version latest = GetLatestVersion(); Version current = new Version(Application.ProductVersion); if (current < latest) { // you need an update } else { // you are up-to-date }
在这个例子中,version.php只有一个像1.0.1.0这样的纯string。
我可以给的另一个提示 – 如何下载更新。 我非常喜欢下一个想法:在应用程序的资源中,有一串CLR代码,它们可以通过CodeDom(即使用CodeDom)编译到一个临时文件夹,主应用程序调用它并closures。 更新程序读取参数,设置或registry并下载新模块。 并调用删除所有临时文件的主要应用程序。 完成!
(但是这里的一切都是关于.NET的)
最简单的解决scheme(由许多程序使用)运行以前版本的卸载程序,并运行新版本的安装程序(可选地跳过用户已经回答的问题,如EULA)。 唯一的问题是,新版本必须能够从旧版本读取configuration选项。
此外,在Windows上,您不能删除正在使用的可执行文件,因此您可能需要在Temp文件夹中放置一个小型可执行文件,该文件夹运行整个过程,然后在最后从新版本的实例中删除它(或者只是在下一次重启时注册它被删除 )。
最简单的方法是让你的程序查询服务器(网站),看看是否有更新。 如果有更新,您可以向用户显示一条消息,提示用户下载更新的版本并提供链接。
另一个更复杂的解决scheme是创build一个小的windows服务(或Unix守护进程),定期检查是否有更新,这个服务可以下载更新并启动安装程序。
一般的体系结构是,你有一个中央服务器,你知道最新的版本和获取它的位置。 然后程序查询服务器。 我不打算包含示例代码,因为它是服务器上的高度被告,以及您select的格式。 虽然这并不难。
这不是一个完整的答案,而是我最近实施的自动更新机制的一个例子。 这种情况与传统的Firefoxtypes的用户应用程序有点不同,因为它是工作中使用的内部工具。
基本上,这是一个小脚本,pipe理一个Subversion分支的队列,在安装程序中构build和打包。 它读取一个小文件,其中分支的名称被写入,取第一个文件,在文件末尾重新写入,然后启动构build过程,这涉及调用一堆脚本。 每个要构build的分支的configuration都被写入一个.INI文件,并与工具本身一起存储在一个Subversion版本库中。
由于这个工具可以在多台计算机上运行,所以只要我对工具本身或configuration脚本进行了更改,我就想在所有机器上自动更新它。
我实施的方式很简单:当我启动工具时,它变成了“shell”。 这个shell做了两件非常简单的事情:
-
svn update
本身和configuration文件 - 重新启动自己,这次是“内壳”,实际上处理一个configuration(然后再退出)的那个。
这个非常简单的update-in-in-a-loop系统现在为我们提供了很好的服务。 这是非常优雅的,因为它是独立的:自动更新是程序本身。 因为“shell”(自动更新器部分)非常简单,所以不会因为更新而从“内部shell”(每次从更新后的源文件执行)中受益。
有一件事没有被提及,你应该认真考虑运行你的程序的用户可能实际上没有足够的权限来升级它。 这对于商业用户来说应该是相当普遍的,对于家庭用户来说可能不那么普遍。
由于安全原因,我总是使用(自行强加的)有限帐户工作,并且总是让我感到不快,因为大多数自动更新程序只是假设我以pipe理员身份运行,然后在下载失败后不提供其他方式执行更新除了实际closures程序并在pipe理环境中再次运行。 大多数甚至不会caching下载的更新,而必须重新完成。
如果自动更新程序只是在需要的时候提示inputpipe理员凭证,并且继续使用,那就好多了。
由于自动更新是一种常见的情况,因此大多数语言至less有一个软件包可用于支持此function。 (下面我列出了一些可用的软件包)
其中一个非常好的主意是.NET的ClickOnce发行版,它是一个安装程序,可以将应用程序安装在沙箱中,并安装在用户上下文中,因此不需要pipe理员权限。 您可以在发布中configurationClickOnce,以检查每个应用程序启动的更新。
Java有Java Web Start ,它为Java小程序提供了相同types的function。
Delphi有很多关于自动更新的文章,Torry有一个WebUpdate组件列表,例如GoUpdater似乎有很多的function。
他们都使用网站/networking共享来检查新版本,并检索修补程序或完整的安装文件并运行它。 所以你应该尝试为你的应用程序find一个很好的包,以节省你开发和维护自己的解决scheme的麻烦。
在Java-Webstart设置中,启动一个JNLP文件,然后触发下载运行应用程序所需的Jar文件。 每次webstart检查是否有较新版本的Jars,并将它们下载replace本地caching的。 使用一个名为jardiff的工具,你将只能创build新的瓶子,并通过服务器分配这些(比如只获得一个更新)。
优点:
- 总是最新的
缺点:
- 你需要一个应用服务器(tomcat,JBoss)来分发文件
- 你需要互联网连接才能获得应用程序
阅读卡尔Seleborgs的答案给了我一些通用的代码库可能是有用的想法。
svn带有一个名为svnsync的工具,它的行为类似于svn导出,但是跟踪你的导出的实际版本。
有人可以利用这个系统,以便只从用户实际修订中获取更改的文件。
实际上,您将拥有一个编译了二进制文件的存储库,并且运行svnsync只会获取已修改的二进制文件。 它也可以将本地更改与基于文本的configuration文件合并为新的configuration选项。
安装补丁程序的function基本上是安装程序的基本function之一。 安装程序软件logging在许多地方,但通常在每个安装程序的基础上:有Microsoft安装程序 (带有Install Shield扩展), Ruby gems , Java .jar文件,各种Linux软件包pipe理器系统( RPM , Apt-get )和其他。
这些都是复杂的系统,一般可以解决程序打补丁的问题,但是对于稍微不同的系统来说。 要决定什么是最适合您的,请考虑您的应用程序最类似这些系统中的哪一个。 滚动你自己很好,但看看这些系统是一个开始的地方。
您可以编写应用程序的内部模块来执行更新。 您可以编写外部迷你应用程序来执行更新。
另外看看.NET的即时编译技术,可以根据需要即时创build这种小型应用程序。 例如, http://fly.sf.net/
我将假设Windows的答案。
这种方式似乎运作良好。
在安装程序中:
1.创build一个以LocalSystem身份运行的手动启动服务,启动时会停止更新。
2.更改服务权限,以便所有用户都可以启动该服务(如果所有用户都应该能够更新没有pipe理员权限)。
3.更改主程序以在使用简单机制开始时检查更新。 如果检测到更新,则提示用户是否要应用它。
4.如果用户接受更新,请启动该服务。
如果体系结构允许,请创build一种方法在运行时监视更新。
您可以使用我的解决scheme( Target Eye项目的一部分)。 http://www.codeproject.com/Articles/310530/Target-Eye-Revealed-part-Target-Eyes-Unique-Auto
如果您正在寻找跨平台的软件更新解决scheme,请查看www.updatenode.com
一些亮点:
- 免费用于开源项目
- 跨平台&开源更新客户端工具
- 已经为最重要的语言进行了本地化
- 易于集成和易于处理
- 基于云的pipe理平台来定义和pipe理更新
- 还提供了对显示消息的支持(通知新事件,产品等)
- Web界面已打开(您可以使用该服务创build自己的客户端)
- 许多使用统计信息,如使用的操作系统,地理位置,版本使用情况等
- 用于移动应用更新的Android API
去尝试一下。
顺便说一句,我是开源客户端的开发团队的一部分。 🙂