软件在线升级-空中下载技术(下-实操篇)

软件在线升级
基于 C++/CLR 的软件在线升级操作指南

一、创建 Visual Studio 2022 工程

  1. 打开 Visual Studio 2022,点击 “创建新项目”。
  2. 在模板搜索框中输入 “C++/CLR”,选择 “CLR 空项目”,点击 “下一步”。
  3. 输入项目名称和保存位置,点击 “创建”,完成基础工程搭建。

二、配置 AWS S3 桶

  1. 登录 AWS 管理控制台,进入 S3 服务页面。
  2. 点击 “创建存储桶”,设置桶名称(需全局唯一)、所属区域等信息,其他选项保持默认,点击 “创建”。
  3. 上传软件更新包到 S3 桶,记住文件的存储路径,例如https://your-bucket-name.s3.amazonaws.com/updates/your_update_file.exe 。
  4. 配置 S3 桶权限,确保可以通过 HTTP 请求访问更新包文件,可在桶的 “权限” 选项卡中设置合适的访问策略
{
  "version": "2.1.0",
  "releaseDate": "2024-10-25",
  "updateType": "major",
  "changelog": [
    {
      "type": "security",
      "title": "修复远程代码执行漏洞",
      "description": "解决了CVE-2024-12345漏洞,该漏洞允许攻击者通过恶意文件触发缓冲区溢出"
    },
    {
      "type": "feature",
      "title": "新增多语言支持",
      "description": "支持英语、中文、日语三种界面语言,可在设置中切换"
    },
    {
      "type": "improvement",
      "title": "性能优化",
      "description": "文件加载速度提升40%,内存占用降低25%"
    }
  ],
  "upgradeTips": [
    "建议在Wi-Fi环境下进行更新",
    "更新前请备份重要数据"
  ],
  "downloadUrl":"https://xxxxx.mis"
}

三、实现版本检测功能

在项目中添加一个新的头文件VersionChecker.h和源文件VersionChecker.cpp
VersionChecker.h 内容

#pragma once
#include <string>
#include <curl/curl.h>

namespace UpdateChecker {
    std::string GetRemoteVersion(const std::string& url);
}

VersionChecker.cpp 内容

#include "VersionChecker.h"
#include <iostream>

std::string UpdateChecker::GetRemoteVersion(const std::string& url) {
    CURL* curl = curl_easy_init();
    std::string response;

    if (curl) {
        curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, [](void* contents, size_t size, size_t nmemb, void* userp) -> size_t {
            ((std::string*)userp)->append((char*)contents, size * nmemb);
            return size * nmemb;
            });
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);

        CURLcode res = curl_easy_perform(curl);
        if (res != CURLE_OK) {
            std::cerr << "curl_easy_perform() failed: " << curl_easy_strerror(res) << std::endl;
        }

        curl_easy_cleanup(curl);
    }
    return response;
}

在主程序中调用该函数检测版本,假设服务器返回的版本号存储在https://your-bucket-name.s3.amazonaws.com/version.txt:

#include "VersionChecker.h"
#include <iostream>

int main() {
    std::string remoteVersion = UpdateChecker::GetRemoteVersion("https://your-bucket-name.s3.amazonaws.com/version.txt");
    std::string localVersion = "1.0.0"; // 假设本地版本号
    if (remoteVersion > localVersion) {
        std::cout << "有可用更新!" << std::endl;
    }
    else {
        std::cout << "当前为最新版本" << std::endl;
    }
    return 0;
}

四、使用 HTTP Range 实现断点续传下载

添加Downloader.hDownloader.cpp文件。

Downloader.h 内容

#pragma once
#include <string>
#include <curl/curl.h>
#include <fstream>

namespace Downloader {
    bool DownloadFile(const std::string& url, const std::string& localFilePath, const long long resumeByte = 0);
}

Downloader.cpp 内容

#include "Downloader.h"
#include <iostream>

bool Downloader::DownloadFile(const std::string& url, const std::string& localFilePath, const long long resumeByte) {
    CURL* curl = curl_easy_init();
    std::ofstream outFile(localFilePath, std::ios::binary | (resumeByte > 0 ? std::ios::app : std::ios::trunc));

    if (curl && outFile) {
        curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, [](void* contents, size_t size, size_t nmemb, void* userp) -> size_t {
            ((std::ofstream*)userp)->write((char*)contents, size * nmemb);
            return size * nmemb;
            });
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &outFile);

        if (resumeByte > 0) {
            char rangeHeader[100];
            snprintf(rangeHeader, sizeof(rangeHeader), "Range: bytes=%lld-", resumeByte);
            curl_easy_setopt(curl, CURLOPT_HTTPHEADER, curl_slist_append(nullptr, rangeHeader));
        }

        CURLcode res = curl_easy_perform(curl);
        if (res != CURLE_OK) {
            std::cerr << "curl_easy_perform() failed: " << curl_easy_strerror(res) << std::endl;
            outFile.close();
            curl_easy_cleanup(curl);
            return false;
        }

        outFile.close();
        curl_easy_cleanup(curl);
        return true;
    }
    if (curl) {
        curl_easy_cleanup(curl);
    }
    if (outFile) {
        outFile.close();
    }
    return false;
}

在检测到有更新时调用下载函数:

#include "VersionChecker.h"
#include "Downloader.h"
#include <iostream>

int main() {
    std::string remoteVersion = UpdateChecker::GetRemoteVersion("https://your-bucket-name.s3.amazonaws.com/version.txt");
    std::string localVersion = "1.0.0"; 
    if (remoteVersion > localVersion) {
        std::cout << "有可用更新!开始下载..." << std::endl;
        std::string updateUrl = "https://your-bucket-name.s3.amazonaws.com/updates/your_update_file.exe";
        std::string localFilePath = "C:\\temp\\your_update_file.exe";
        if (Downloader::DownloadFile(updateUrl, localFilePath)) {
            std::cout << "下载完成" << std::endl;
        }
    }
    else {
        std::cout << "当前为最新版本" << std::endl;
    }
    return 0;
}

五、使用 Microsoft Visual Studio Installer Projects 2022 打包升级程序

  1. 在解决方案资源管理器中,右键点击解决方案,选择 “添加”->“新建项目”。
  2. 在模板搜索框中输入 “Installer”,选择 “Microsoft Visual Studio Installer Projects 2022”,点击 “下一步”,输入项目名称,点击 “创建”。
  3. 在安装项目中,右键点击 “应用程序文件夹”,选择 “添加”->“项目输出”,选择之前创建的 C++/CLR 项目,确定添加主输出和依赖项。
  4. 配置安装项目属性,如安装路径、快捷方式等。
  5. 生成安装项目,得到.msi.exe安装包。后续升级包也可通过类似方式打包,将更新后的文件添加到安装项目中重新生成。

六、后续处理与优化

  1. 版本对比逻辑优化:采用更规范的语义化版本解析和对比算法,确保版本比较的准确性。
  2. 错误处理增强:在下载和版本检测过程中,完善错误提示和日志记录功能,方便排查问题。
  3. 用户交互设计:结合 C++/CLR 开发的 UI 界面,设计友好的更新提示和下载进度显示界面,提升用户体验 。

 

posted @ 2025-04-29 10:33  王廷胡_白嫖帝  阅读(310)  评论(0)    收藏  举报