76

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

不幸的是,无论我怎么看,我都无法在任何地方找到有关此过程的信息。似乎已经实施的自动更新程序要么是专有的,要么被认为不重要。

实现在网络上查找更新并在可用时下载更新的系统似乎相当容易。自动更新程序的那部分将在不同的实现之间发生显着变化。问题是应用补丁的不同方法是什么。只是下载文件并用新文件替换旧文件、运行已下载的迁移脚本、猴子修补系统的某些部分等等?概念是首选,但 Java、C、Python、Ruby、Lisp 等中的示例将不胜感激。

4

17 回答 17

54

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

最普遍的理念是应用程序检查某个家庭位置(网址、Web 查询、公司网络位置等)以询问它的版本是否是最新的,或者询问最新的版本是什么。如果答案要求更新,则该过程将因每种情况而异。

一种流行的替代方法是在启动应用程序时邀请主位置运行脚本。例如,该脚本可以检查版本、下载更新(如有必要)以及询问使用反馈。

如果您缩小参数范围,我们可能会提供更好的帮助。

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

于 2008-10-24T03:12:38.493 回答
21

请务必考虑提取有关更新的信息以及更新二进制文件本身的安全隐患。

你相信下载的来源吗?您可能会打电话回家获取更新,但如果中间有人重定向到恶意服务器怎么办。HTTPS 或类似的安全连接会有所帮助,但建议使用数字签名检查仔细检查您最终下载的位。

于 2009-01-28T06:45:53.607 回答
8

首先,您需要在您的应用程序主页网站上找到一个最新版本的文件。我认为最好的方法是为此任务提供特殊的 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)

于 2008-12-04T06:41:53.390 回答
6

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

此外,在 Windows 上,您无法删除正在使用的可执行文件,因此您可能需要在 Temp 文件夹中放置一个小型可执行文件,该文件夹会运行整个过程,然后在最后从新版本的实例中删除它已启动(或仅将其注册以在下次重新启动时将其删除)。

于 2009-01-28T07:51:31.353 回答
2

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

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

一般架构是您拥有一个您控制的中央服务器,该服务器知道最新版本以及从何处获取它。然后程序查询服务器。我不会包含示例代码,因为它在服务器和您选择的格式上是高度被告。不过这并不难。

于 2008-10-24T03:14:03.747 回答
2

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

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

因为这个工具可以在多台计算机上运行,​​所以我想要一种方法来在我对工具本身或配置脚本进行更改后立即在所有机器上自动更新它。

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

  • svn update在自身和配置文件上
  • 再次启动自身,这次作为“内壳”,实际处理一种配置(然后再次退出)。

这个非常简单的 update-myself-in-a-loop 系统已经为我们服务了几个月了。它非常优雅,因为它是独立的:自动更新程序就是程序本身。因为“外壳”(自动更新程序部分)非常简单,所以它不会像“内壳”一样从更新中受益(每次都从更新的源文件执行)。

于 2009-01-28T07:46:15.920 回答
2

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

一个非常好的想法是用于 .NET 的ClickOnce发行版,它是一个安装程序,可将您的应用程序沙箱化并安装在用户上下文中,因此不需要管理员权限。您可以在发布中配置 ClickOnce 以检查每个应用程序启动时的更新。

Java 有Java Web Start,它为 Java 小程序提供了相同的功能。

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

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

于 2009-01-28T08:28:41.950 回答
2

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

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

如果自动更新程序在需要时只提示输入管理员凭据并继续使用它会更好。

于 2009-01-29T23:53:30.250 回答
1

我将假设 Windows 的答案。

这种方式似乎运作良好。

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

如果架构允许,请创建一种在更新运行时监控更新的方法。

于 2009-01-30T00:09:15.743 回答
0

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

优点:

  • 始终保持最新

缺点:

  • 您需要一个应用程序服务器(tomcat、JBoss)来分发文件
  • 您需要互联网连接才能获得应用程序
于 2009-01-28T07:33:47.100 回答
0

阅读 Carl Seleborgs 的回答给了我一些想法,通用代码存储库如何有用。

svn 带有一个名为 svnsync 的工具,它的行为类似于 svn 导出,但会跟踪导出的实际版本。

有人可以利用该系统仅从用户的实际修订中获取更改的文件。

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

于 2009-01-28T07:56:46.100 回答
0

为程序安装补丁的功能基本上是安装程序的基本功能之一。安装程序软件记录在许多地方,但通常以每个安装程序为基础:Microsoft Installer(带有 Install Shield Extensions)、Ruby gemsJava .jar文件、各种 Linux 包管理器系统(RPMApt-get)等.

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

于 2009-01-28T08:05:32.153 回答
0

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

还要看看 .NET on-the-fly 编译技术,它使得按需动态创建这样的迷你应用程序成为可能。例如, http: //fly.sf.net/

于 2009-01-28T08:56:50.707 回答
0

您可以使用我的解决方案(Target Eye项目的一部分)。 http://www.codeproject.com/Articles/310530/Target-Eye-Revealed-part-Target-Eyes-Unique-Auto

于 2015-04-28T20:53:48.180 回答
0

如果您的软件是开源的,并且针对 Linux 或开发人员。将您的软件安装为 git repo 很有趣。并让它偶尔或每次启动时都会拉动稳定的分支。

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

于 2018-11-27T09:43:52.583 回答
0

经过数小时为这个问题寻找一些可行的解决方案后,我终于实现了适用于 Linux 和 Windows 的 python 脚本的自动更新机制。

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

完整的源代码和解释可以在这里找到。

于 2021-08-30T07:47:23.387 回答
-1

如果您正在寻找跨平台软件更新解决方案,请访问www.updatenode.com

一些亮点:

  • 开源项目免费
  • 跨平台开源更新客户端工具
  • 已经针对最重要的语言进行了本地化
  • 易于集成且易于处理
  • 基于云的管理平台,用于定义和管理更新
  • 提供对显示消息的额外支持(关于新事件、产品等的通知)
  • Web 界面已打开(您可以使用该服务创建自己的客户端)
  • 许多使用统计,如使用的操作系统、地理位置、版本使用等。
  • 用于移动应用更新的 Android API

就试一试吧。

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

于 2014-03-25T13:06:00.540 回答