【问题标题】:Automatically checking for a new version of my application自动检查我的应用程序的新版本
【发布时间】:2010-09-08 13:20:02
【问题描述】:

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

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

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

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


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

喜欢

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

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

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

【问题讨论】:

    标签: c++ qt


    【解决方案1】:

    我绝对建议只对您的网站进行简单的 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 加载可执行内容然后实际执行而被处以绞刑(不一定按此顺序)。

    所以为了尽量降低伤害,

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

    做你将要做的事情并不有趣——尤其是当你像我无数次那样与非技术倾向的用户打交道时。

    【讨论】:

    • 非常完整的答案;但我想补充一点:如果可能,请使用 HTTPS/SSL。虽然这里可能没有必要:有一些工具可以嗅探这样的hey, is there an update?''-questions and simply answering yes,在这里,请拿走我的代码并安装/执行它''...
    • 比使用 SSL 更好的是实际签署更新二进制文件并检查其签名。 SSL 仅证明从中加载更新的 url 是颁发(任何)证书的目的。为了完全节省,我将使用我的公钥部署要更新的应用程序,使用我的私钥对更新进行签名,然后检查更新本身。
    【解决方案2】:

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

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

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

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

    【讨论】:

      【解决方案3】:

      马丁,

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

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

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

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

      【讨论】:

      • 同意!我们不通过互联网更新。我们的“启动器”只触发一个进程,更新代码在应用程序中。在任何一种情况下,用户都不会自动执行此操作,我们通过 VNC 执行此操作,因为它是一个医疗数据库,并且我们不想在有数据库脚本要运行的情况下冒险使用数据库。不错
      【解决方案4】:

      在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 脚本可以返回的内容来告诉客户端它是否是重要的、强制性的更新。

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

      你的可能性是无限的。

      【讨论】:

        【解决方案5】:

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

        【讨论】:

          【解决方案6】:

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

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

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

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

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

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

          【讨论】:

          • 大声笑,我们不会自动更新。用户从不自动更新。我们这样做:) 我们用户的数据库包含非常重要的医疗数据,我们所做的是更新服务器(使用内部向导)备份数据库并执行脚本,然后如果一切正常,它会“发布”更新
          【解决方案7】:

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

          【讨论】:

            【解决方案8】:

            如果您将文件保存在 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");
            

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

            【讨论】:

              【解决方案9】:

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

              解析xml文件后可以判断是否需要新版本,用libcurl下载新版本并安装。

              【讨论】:

              • Qt 具有网络模块,因此可以在 Qt 中轻松处理 HTTP 请求,而无需使用额外的库。
              【解决方案10】:

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

              【讨论】:

                【解决方案11】:

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

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

                【讨论】:

                  【解决方案12】:

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

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

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

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

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

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 2013-01-21
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2011-03-11
                    相关资源
                    最近更新 更多