我应该如何实现自动更新?

许多程序包括自动更新程序,程序偶尔会在线查找更新,然后下载并应用找到的任何更新。程序错误得到修复,支持文件得到修改,事情(通常)得到了改善。

不幸的是,无论我多么努力地寻找,我都找不到关于这个过程的任何信息。似乎已经实现的自动更新程序要么是专有的,要么被认为不重要。

实现在网络上查找更新并在可用时下载这些更新的系统似乎相当容易。从实现到实现,自动更新程序的这一部分将发生重大变化。问题是 申请补丁的不同方法是什么。只是下载文件,用新文件替换旧文件,运行下载的迁移脚本,修补系统的某些部分,等等?概念是首选的,但是 Java、 C、 Python、 Ruby、 Lisp 等的例子将会很受欢迎。

34683 次浏览

我认为“语言不可知论者”将是一个限制因素。应用程序的形状和大小如此之多,以至于没有一个放之四海而皆准的答案。我已经用几种语言实现了几个自动更新程序,没有两个是相似的。

最普遍的理念是,应用程序检查一些主页位置(网址、网络查询、公司网络位置等) ,要么询问它的版本是否是最新的,要么询问最新的版本是什么。如果答案要求更新,那么这个过程对于每种情况都是不同的。

一种流行的替代方法是在应用程序启动时邀请主站点运行脚本。例如,该脚本可以检查版本,必要时下载更新,并请求用法反馈。

如果你缩小范围,我们也许能帮得上忙。

更新: “修补”的方法也取决于应用程序的性质,这里有非常广泛的多样性。例如,如果您只有一个可执行文件,那么替换该可执行文件可能是最实际的做法。如果您的应用程序有许多文件,您应该寻找尽量减少替换文件数量的方法。如果您的应用程序是高度自定义或参数化的,那么您应该尽量减少重新定制的工作。如果应用程序使用解释代码(例如 Excel VBA 应用程序或 MS Access MDB 应用程序) ,则可以替换部分代码。在 Java 应用程序中,您可能只需要替换一个 JAR 文件,甚至替换 JAR 内容的一个子集。您还需要有一种方法来识别当前客户端版本,并适当地更新它。我可以一直说下去,但我希望你明白我关于多样性的观点。很多时候,最好的答案通常都是这样开头的: “嗯,这要看情况... ... !”这就是为什么这么多答案包括“请缩小参数。”

最简单的方法是让你的程序查询一个服务器(网站) ,看看是否有更新。如果有更新,您可以向用户显示一条消息,提示他们下载更新的版本并提供链接。

另一种更复杂的解决方案是创建一个小的 windows 服务(或 unix 守护进程) ,定期检查是否有更新,该服务可以下载更新并启动安装程序。

一般体系结构是,您拥有一个可以控制的中央服务器,该服务器知道最新版本以及从哪里获取它。然后程序查询服务器。我不打算包括示例代码,因为它是高度被告的服务器和格式您选择。不过也不是很难。

首先,您需要在您的应用程序主页网站上的最新版本的文件。 我认为在发布新版本/每晚构建完成后,为这个任务设置特殊的 SQL 表并自动填充它的最佳方式。 您的应用程序创建新线程,请求内置的 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。

另一个我可以提供的建议-如何下载更新。 我非常喜欢下一个想法: 在应用程序的资源中有一串 CLR 代码,你可以动态地(使用 CodeDom)编译到一个临时文件夹中,主应用程序调用它并关闭它。更新程序读取参数、设置或注册表并下载新模块。并调用删除所有临时文件的主应用程序。成交!

(但是这里的一切都是关于.NET 的)

还要确保考虑下载有关更新的信息以及更新二进制文件本身所涉及的安全问题。

您信任下载源吗?你可能会打电话回家问你的最新情况,但是如果中间有一个人重定向到一个恶意服务器怎么办。HTTPS 或类似的安全连接将会有所帮助,但是建议使用数字签名检查对您最终下载的位进行双重检查。

在 Java-Webstart 设置中,您启动一个 JNLP 文件,然后触发运行应用程序所需的 Jar 文件的下载。每次 webstart 都会检查是否有更新版本的 Jars,并下载它们来替代本地缓存的版本。使用一个名为 jardiff 的工具,你只会创建新的 jar 的差异,并通过服务器发布这些差异(例如,只获得更新)。

优点:

  • 随时更新

缺点:

  • 您需要一个应用程序服务器(tomcat,JBoss)来分发文件
  • 你需要一个互联网连接,以获得应用程序

这并不是一个完整的答案,而是我最近实现的自动更新机制的一个例子。这种情况与传统 Firefox 类型的用户应用程序稍有不同,因为它是工作中使用的内部工具。

基本上,它是一个小脚本,用于管理要构建并打包到安装程序中的 Subversion 分支队列。它读取一个小文件,其中写入了分支的名称,接受第一个分支,在文件末尾重新写入它,然后启动构建过程,其中涉及调用大量脚本。要生成的每个分支的配置都写在。INI 文件,与工具本身一起存储在 Subversion 存储库中。

因为这个工具可以在多台计算机上运行,所以我需要一种方法,只要我对工具本身或配置脚本做了更改,就可以在所有计算机上自动更新它。

我实现它的方法很简单: 当我启动这个工具时,它就变成了一个“外壳”。这个外壳做两件非常简单的事情:

  • svn update对其本身和对配置文件
  • 再次启动自身,这次是作为“内部 shell”启动的,它实际上处理一个配置(然后再次退出)。

这个非常简单的自我更新循环系统已经很好地为我们服务了几个月了。它非常优雅,因为它是自包含的: 自动更新程序就是程序本身。因为“外层 shell”(自动更新部分)非常简单,所以它不能像“内层 shell”(每次都从更新的源文件中执行)那样从更新中获益并不重要。

最简单的解决方案(许多程序使用)是运行前一个版本的卸载程序和运行新版本的安装程序(可以跳过用户已经回答的问题,比如 EULA)。唯一的问题是新版本必须能够从旧版本读取配置选项。

另外,在 Windows 上你不能删除一个正在使用的可执行文件,所以你可能想把一个小的可执行文件放到 Temp 文件夹中,这个文件夹运行整个过程,然后在最后从新版本的实例中删除它(或者仅仅是 在下次重新启动时注册并删除它)。

通过阅读 Carl Seleborgs 的答案,我了解到一个通用代码库是如何有用的。

Svn 附带了一个名为 svnsync 的工具,其行为类似于 svn 导出,但是会跟踪导出的实际修订。

有人可以利用这个系统,以便只从用户实际修订中获取已更改的文件。

实际上,您将拥有一个已编译二进制文件的存储库,而运行 svnsync 只能获取已修改的二进制文件。它还可以使用新的配置选项合并对基于文本的配置文件的本地更改。

为程序安装补丁的功能基本上是安装程序的基本功能之一。安装程序软件在很多地方都有记录,但通常是以每个安装程序为基础的: 有 微软安装程序(带安装盾扩展)、 红宝石文件、各种 Linux 包管理系统(转速明白)和其他。

这些都是复杂的系统,解决的问题,修补程序一般,但略有不同的系统。要决定什么最适合您,请考虑您的应用程序最类似于这些系统中的哪一个。自己滚动是好的,但是看看这些系统是一个开始的地方。

因为自动更新是一个常见的场景,所以大多数语言至少有一个可用的包来支持这一点。(下面我列出了一些可用的软件包)

其中一个非常好的想法是 点击一次发行版。NET,这是一个安装程序,沙箱您的应用程序和安装在用户上下文,所以没有管理员的权限要求。可以在发布中配置 ClickOnce 以检查每个应用程序启动时的更新。

Java 有 Java 网站开始,它为 Java applet 提供了同样的功能。

Delphi 有许多关于自动更新的文章,Torry 有一个 WebUpdate 组件的列表,例如 GoUpdater似乎有一个非常广泛的功能。

他们都使用网站/网络共享来检查新版本,然后检索补丁或完整的安装文件并运行它。因此,您应该尝试为您的应用程序找到一个好的软件包,以节省开发和维护您自己的解决方案的麻烦。

您可以编写应用程序的内部模块来执行更新。您可以编写一个外部迷你应用程序来执行更新。

也看看。NET 的动态编译技术,使得这样的小型应用程序的动态创建成为可能。例如,http://fly.sf.net/

有一件事没有真正提到,那就是您应该认真考虑运行您的程序的用户可能实际上没有足够的权限来升级它。至少对于商业用户来说,这应该是相当普遍的,对于家庭用户来说可能就不那么普遍了。

出于安全原因,我总是使用一个(自我强加的)有限的帐户,大多数自动更新程序只是假设我是以管理员身份运行的,然后在下载后失败,除了实际关闭程序并在管理上下文中再次运行之外,没有提供其他执行更新的方法,这总是让我生气。大多数甚至不缓存下载的更新,必须重新来过。

如果自动更新程序在需要时提示输入管理员凭证并继续运行,那么效果会更好。

我假设答案是 Windows。

这种方法似乎很有效。

在安装程序中:
1. 创建一个手动启动服务,该服务作为 LocalSystem 运行,在启动时进行更新,然后停止。
2.更改服务权限,以便所有用户都可以启动服务(如果所有用户都应该能够更新管理权限)。
3.更改主程序以便在使用简单机制启动时检查更新。如果它检测到一个更新,如果用户想要应用它,则提示。
4. 如果用户接受更新,则启动服务。

如果体系结构允许,那么创建一种方法来监视正在运行的更新。

如果您正在搜索跨平台软件更新解决方案,请参阅 Www.updatenode.com

一些亮点:

  • 免费的开放源码项目
  • 跨平台和开源更新客户端工具
  • 已经为最重要的语言本地化了
  • 易于整合,易于操作
  • 基于云的管理平台来定义和管理更新
  • 提供显示消息的额外支持(通知新事件、产品等)
  • Web 界面是开放的(您可以使用该服务创建自己的客户端)
  • 许多使用统计数据,如使用的操作系统、地理位置、版本使用情况等。
  • 用于移动应用程序更新的 Android API

试试吧。

顺便说一句,我是开源客户端开发团队的一员。 :)

如果您的软件是开源的,目标是 Linux 或开发人员。将您的软件作为 git repo 安装是很有趣的。让它偶尔或者每次发射时拉动稳定的分支。

当您的应用程序通过 npm、 sbt、 mavan、 stack、 elm-package 或类似方式进行管理时,这尤其容易。

在为这个问题寻找了几个小时的工作解决方案之后,我终于实现了在 Linux 和 Windows 上运行的 python 脚本的自动更新机制。

简而言之——脚本在运行实际工作之前检查 S3上的更新,如果可以下载,解压缩,创建或更新符号链接(或 Windows 上的连接) ,并重新运行带有原始参数的新版本的脚本。

完整的源代码和解释可以找到 给你