【问题标题】:Simple update mechanism for C/GTK app on WindowsWindows 上 C/GTK 应用程序的简单更新机制
【发布时间】:2010-10-30 13:44:38
【问题描述】:

我正在开发一个 C/GTK 应用程序。我将很快发布一个新版本,我认为在其中包含一些更新机制会很有用,以便应用程序能够自行更新。

我真的只需要简单的东西;如果它只在 Windows 上运行就足够了,因为在 Linux 上,应用程序位于 repo 中,因此用户可以轻松更新它。

所以我想问一下,是否有一些简单易行的方法可以做到这一点(比如一些小型库),还是我必须自己实现它?

谢谢。

附言

我真的想要一些非常简单的东西,例如,假设应用程序将从包含最新版本号的服务器下载网页。如果应用程序版本号!=服务器版本号,它将获取一个 setup.exe,以某种方式检查其真实性并运行它。

【问题讨论】:

    标签: c windows gtk auto-update


    【解决方案1】:

    这可能不是问题的完整答案,但如果您要自己实施,可能需要考虑以下几点:

    对于“检查更新”部分,无需实际下载,您可以从在线位置下载包含最新版本字符串(例如 1.24)的文本文件。这段代码 sn-p 应该为 Windows 版本完成工作(虽然我没有测试过):

    #include <wininet.h>
    
    _Bool CheckForUpdate() {
        DWORD flags = 0; // Not really used. DWORD == unsigned long
    
        if (!InternetGetConnectedState(&flags, 0)) {
            // The user is not connected to the Internet. Finished?
        }
        
        // Open the connection (HINTERNET == void *):
        HINTERNET connection = InternetOpen("User Agent", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
        if (http == NULL) {
            // Error.
            ...
        }
        
        HINTERNET updateFile = InternetOpenUrl(connection, "URL", NULL, FLAGS, 0);
        if (updateFile == NULL) {
            // Something went wrong.
            ...
            InternetcloseHandle(connection); // Close the handle.
            ...
        }
        
        // Reached here, we have the connection up, reading the file:
        char latestVersion[10] = {0};
        DWORD bytesRead = 0;
        if (InternetReadFile(updateFile, latestVersion, sizeof(latestVersion), &bytesRead) == FALSE) {
            // Error.
            ...
            InternetCloseHandle(updateFile);
            InternetCloseHandle(connection);
            ...
        }
        
        // Internet stuff is finished, so the handles can be closed now:
        InternetCloseHandle(updateFile);
        InternetCloseHandle(connection);
        
        // Check if there's a new version available:
        if (strcmp(latestVersion, CURRENT_VERSION) > 0) {
            // An update is available.
            return 1;
        } else {
            // No new updates available.
            return 0;
        }
    }
    

    有我在答案末尾使用的 Wininet 函数的文档的链接,您可以在其中查看每个参数的用途。

    当调用InternetOpen() 时,用户代理字符串可能是例如您的应用程序名称。我写了INTERNET_OPEN_TYPE_DIRECT,因为它是最常见的设置,没有指定代理配置。

    InternetOpenUrl() 调用中,第二个参数应该是作为NULL 终止字符串的文本文件的URL。对于该调用中的FLAGS 参数,请检查您拥有的不同文档的在线文档(查看帖子底部的链接)。例如,可能的标志组合如下:

    INTERNET_FLAG_RELOAD | INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_NO_AUTH | INTERNET_FLAG_NO_COOKIES | INTERNET_FLAG_NO_UI
    

    strcmp() 调用也应该适用于版本之间的字母,因此按照上面的示例,“1.24c”应该是比“1.24”或“1.24a”更新的版本。

    如果您有多个发布路径(例如 beta 版本),您可以在文本文件中使用多个字段或拥有多个文件。如果您不想将不稳定的版本推送给所有用户,而只推送给愿意使用此类构建的用户,这可能会很有用。

    如果读取文件时没有错误,您还可以使用带有HTTP_QUERY_STATUS_CODE 标志的HttpQueryInfo() 函数添加检查以查看HTTP 状态代码是否为200(正常)。

    无论如何,这一切只是为了获得新版本的确认,您可以通过消息通知您的用户或使用类似的方案来下载新的安装应用程序。对于身份验证阶段,您可以将设置文件的校验和添加到版本文件中,并在文件下载后计算它。

    Wininet API 在线文档的链接:

    希望对您有所帮助。

    【讨论】:

    • 谢谢,这绝对有帮助,+1。还没有选择答案,但鉴于似乎没有一个库可以做我想做的事,我可能最终会自己实现它,在这种情况下我会接受这个答案。
    • 使用您的代码作为我自己的库的起点来执行此操作 - 在 README 文件中感谢您,再次感谢!详情见我的回答。
    • 好!我很高兴它适合你。当您不断改进它时,您将不得不面对诸如代理管理或 FTP 文件检索(现在连接是 HTTP 连接)之类的事情,但这是一个很好的起点;)。
    【解决方案2】:

    omaha 很酷,如果你有资源设置相应的服务器端。

    【讨论】:

    • 我讨厌谷歌的更新方式。更新检查没有理由比我使用程序运行得更频繁,按计划运行更新程序只是愚蠢的。
    • 快速浏览一下,这对于我需要的东西来说太复杂了——添加了一个 PS 来澄清问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多