23

为了满足客户的功能要求,我希望我的应用程序在 Internet 可用时检查我们的网站是否有新版本可用。

问题是我不知道在服务器端必须做什么。

我可以想象我的应用程序(使用 Qt 在 C++ 中开发)必须向服务器发送请求(HTTP ?),但是什么会响应这个请求呢?为了通过防火墙,我想我必须使用端口 80 ?它是否正确 ?

或者,对于这样的功能,我是否必须要求我们的网络管理员打开一个特定的端口号,我将通过该端口号进行通信?


@ pilif:感谢您的详细回答。对我来说还有一些不清楚的地方:

http://www.example.com/update?version=1.2.4

然后你可以返回你想要的任何东西,也可能是新版本安装程序的下载 URL。

我该如何退货?它将是一个 php 或 asp 页面(我对 PHP 或 ASP 一无所知,我不得不承认)?我怎样才能解码?version=1.2.4零件以便相应地返回一些东西?

4

12 回答 12

38

我绝对建议您对您的网站进行简单的 HTTP 请求。其他一切都注定要失败。

我会向您网站上包含本地应用程序版本的特定页面发出 HTTP GET 请求。

http://www.example.com/update?version=1.2.4

然后你可以返回你想要的任何东西,也可能是新版本安装程序的下载 URL。

为什么不把最新版本的静态文件放到服务器上,让客户端决定呢?因为您可能希望(或需要)控制该过程。也许 1.2 将来不会与服务器兼容,因此您希望服务器强制更新到 1.3,但是从 1.2.4 更新到 1.2.6 可能并不重要,因此您可能希望向客户端显示可选更新。

或者您想对已安装的基础进行细分。

管他呢。通常,我了解到最好在服务器上保留尽可能多的智能,因为服务器是您最终控制的对象。

这里有一些该领域的经验,这里有一个小的预览,可以(并且将 - 相信我)出错:

  • 您的应用程序将被各种个人防火墙应用程序阻止发出 HTTP 请求。
  • 相当大比例的用户没有实际进行更新过程所需的权限。
  • 即使您的用户允许旧版本通过他们的个人防火墙,该工具也会抱怨,因为 .EXE 已更改,并会建议用户不要允许新的 exe 连接(用户通常在此处遵守其安全工具的意愿) .
  • 在托管环境中,您将因从 Web 加载可执行内容然后实际执行它而被枪杀(不一定按此顺序)。

所以为了尽量降低伤害,

  • 无法连接到更新服务器时静默失败
  • 在更新之前,请确保您对安装目录具有写入权限,如果您没有,或者根本不更新,则警告用户。
  • 为管理员提供关闭自动更新的方法。

做你将要做的事情并不有趣——尤其是当你与我不得不多次处理的非技术倾向的用户打交道时。

于 2008-09-11T12:29:19.823 回答
21

Pilif 的回答很好,我对此也有很多经验,但我想补充一点:

请记住,如果您启动 yourapp.exe,那么“更新程序”将尝试用最新版本覆盖 yourapp.exe。根据您的操作系统和编程环境(您提到过 C++/QT,我没有这方面的经验),您将无法覆盖yourapp.exe,因为它将被使用。

我所做的是创建一个启动器。我有一个 MyAppLauncher.exe,它使用配置文件(xml,非常简单)来启动“真正的 exe”。如果存在新版本,Launcher 可以更新“真正的 exe”,因为它没有被使用,然后重新启动新版本。

只要记住这一点,你就会很安全。

于 2008-09-11T12:40:23.980 回答
7

马丁,

你当然是完全正确的。但我会随安装程序一起提供启动器。或者只是下载安装程序,启动它并尽快退出。原因是启动器中的错误。您永远都不会希望依赖于无法更新(或忘记包含在初始 drop 中)的组件。

因此,我在应用程序更新过程中分发的有效负载只是标准安装程序,但没有任何重要的 UI。一旦客户端检查了安装程序是否有机会成功运行,并且一旦下载了更新程序,它就会运行它并自行退出。

然后更新程序运行,将其有效负载安装到原始安装目录中并重新启动(希望已更新)应用程序。

仍然:这个过程很麻烦,当您的应用程序具有广泛的使用重点时,您最好在 Windows 平台上实现自动更新功能之前三思而后行。

于 2008-09-11T12:48:11.387 回答
6

在 php 中,事情很简单:

<?php
    if (version_compare($_GET['version'], "1.4.0") < 0){
        echo "http://www.example.com/update.exe";
    }else{
        echo "no update";
    }
?>

当然,如果您可以扩展它,那么当前可用的版本不会在脚本中硬编码,但这只是为了说明这一点。

在您的应用程序中,您将拥有以下伪代码:

result = makeHTTPRequest("http://www.example.com/update?version=" + getExeVersion());
if result != "no update" then
    updater = downloadUpdater(result);
    ShellExecute(updater);
    ExitApplication;
end;

随意扩展“协议”,通过指定 PHP 脚本可以返回的内容来告诉客户端它是否是重要的、强制性的更新。

或者您可以添加一些文本以显示给用户 - 可能包含一些有关更改内容的信息。

你的可能性是无限的。

于 2008-09-11T16:06:49.880 回答
4

我的 Qt 应用程序只是使用 QHttp 从我的网站上读取包含最新版本号的微小 XML 文件。如果这大于当前版本号,则可以选择转到下载页面。非常简单。工作正常。

于 2008-09-13T14:37:34.133 回答
2

我同意@Martin 和@Pilif 的回答,但补充一下;

考虑让您的最终用户决定他们是否要在此处实际安装更新,或者延迟安装更新,直到他们完成使用该程序。

我不知道您的应用程序的用途/功能,但是当用户需要在那里执行特定的操作时会启动许多应用程序 - 没有什么比启动应用程序然后被告知它找到了一个新版本更烦人了,而您必须等待它下载,关闭应用程序并重新启动。如果您的程序有其他可能更新的资源(参考文件、数据库等),问题会变得更糟。

我们有一个在大约 400 家商店运行的 EPOS 系统,最初我们认为让程序发现更新并下载它们会很棒(使用包含与您上面的建议非常相似的版本号的文件)......好主意. 直到所有商店在大约同一时间(上午 8 点 45 分到 8 点 50 分)启动他们的系统,并且我们的服务器被击中,为 400 台远程服务器提供 20+Mb 的下载,然后更新本地软件并导致重新开始。混乱 - 没有人能够交易大约 10 分钟。

不用说,这导致我们随后关闭了“检查更新”功能并重新设计它以允许商店将更新“延迟”到当天晚些时候。:-)

编辑:如果 ADOBE 中的任何人正在阅读 - 看在上帝的份上,为什么当我只想启动阅读文档时,该死的杂技阅读器会坚持尝试下载更新和废话?是不是开始时不够慢,而且不够臃肿,因为每次我想阅读 PDF 时都不会浪费我生命中的 20-30 秒来寻找更新?
他们不使用自己的软件吗??!!! :-)

于 2008-09-11T13:32:50.593 回答
1

在服务器上,您可能只有一个简单的文件“latestversion.txt”,其中包含最新版本的版本号(可能还有下载 URL)。然后,客户端只需使用简单的 HTTP 请求(是的,到端口 80)读取此文件以检索http://your.web.site/latestversion.txt,然后您可以对其进行解析以获取版本号。这样您就不需要任何花哨的服务器代码 --- 您只需将一个简单的文件添加到您现有的网站。

于 2008-09-11T12:26:45.277 回答
1

如果您将文件保存在 example.com 上的更新目录中,则此 PHP 脚本应根据前面提到的请求为您下载它们。(您的更新将是 yourprogram.1.2.4.exe

$version = $_GET['version'];    
$filename = "yourprogram" . $version . ".exe";
$filesize = filesize($filename);
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: post-check=0, pre-check=0");
header("Content-type: application-download");
header('Content-Length: ' . $filesize);
header('Content-Disposition: attachment; filename="' . basename($filename).'"');
header("Content-Transfer-Encoding: binary");

这会使您的网络浏览器认为它正在下载应用程序。

于 2008-09-11T13:54:27.483 回答
0

实现这一点的最简单方法是使用libcurl之类的库触发 HTTP 请求,并使其下载包含在线版本以及新版本在线可用的 ini 或 xml 文件。

解析 xml 文件后,您可以确定是否需要新版本,并使用 libcurl 下载新版本并安装它。

于 2008-09-11T12:24:53.470 回答
0

只需在您的服务器上放置一个 (XML) 文件,其中包含最新版本的版本号,以及下载新版本的 URL。然后,您的应用程序可以请求 XML 文件,查看版本是否与自己的版本不同,并采取相应的措施。

于 2008-09-11T12:25:02.410 回答
0

我认为服务器上的简单 XML 文件仅用于版本检查就足够了。

然后,您只需要服务器上的 ftp 帐户和构建系统,该系统能够在构建新版本后通过 ftp 发送文件。该构建系统甚至可以将安装文件/压缩文件直接放在您的网站上!

于 2008-09-11T12:26:08.477 回答
0

如果你想保持它非常基本,只需将 version.txt 上传到网络服务器,其中包含一个整数版本号。根据您下载的最新 version.txt 下载检查,然后只需下载 msi 或安装包并运行它。

更高级的版本是使用 rss、xml 或类似的。最好使用第三方库来解析 rss,如果您愿意,您可以包含向用户显示的有关更改的信息。

基本上你只需要简单的下载功能。

这两种解决方案都只需要您访问从客户端传出的端口 80。这通常不需要对防火墙或网络(在客户端)进行任何更改,您只需要拥有一个面向 Internet 的 Web 服务器(Web 托管、托管或您自己的服务器——所有这些都可以在这里工作)。

有几个可用的商业自动更新解决方案。我会将这些建议留给其他回答者,因为我只有在 .net 方面使用 Click-Once 和 Updater Application Block 的经验(后者不再继续)。

于 2008-09-11T12:27:37.737 回答