首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> 關於VC++

HTTP 線上自動更新程式完整實作:從版本檢查到增量替換

     編輯:關於VC++

為避免每次修改小錯誤都需通知使用者手動更新,開發 HTTP 架構的線上自動更新程式。相較 FTP 方案,HTTP 無需帳號密碼傳輸,資安風險較低。

架構設計與命令列參數


update.exe 程式名 版本號 更新設定檔URL
範例:update.exe VolleyMail 3.0 https://www.extice.com/update/update.ini

核心流程與關鍵程式碼

1. 命令列解析與初始化


CStringArray paraArr;
CUpdateApp::GetCmdLinePara(paraArr);
dlg.m_strSoft = paraArr.GetAt(0);
dlg.m_strVersion = paraArr.GetAt(1);
AfxParseURL(paraArr.GetAt(2), dwType, dlg.m_strServer,
    dlg.m_strIniPath, dlg.m_dwPort);

2. 下載更新設定檔並比對版本


m_cis.SetOption(INTERNET_OPTION_CONNECT_TIMEOUT, 5);
m_pHttp = m_cis.GetHttpConnection(m_strServer, m_dwPort);
m_lbProduct.AddString(m_strSoft + " " + m_strVersion);

// 下載 update.ini 至暫存目錄
CStdioFile csf;
csf.Open(m_strTempDir + "\\update.ini",
    CFile::modeCreate | CFile::modeWrite | CFile::typeBinary);
char buf[2048]; int n;
while ((n = pFile->Read(buf, 2048)) > 0) csf.Write(buf, n);

// 讀取最新版本號
char verBuf[128];
::GetPrivateProfileString(m_strSoft, "VERSION", "1.0",
    verBuf, sizeof(verBuf), m_strTempDir + "\\update.ini");
m_strNewVer = verBuf;

if (atof(m_strVersion) >= atof(verBuf)) {
    m_strStatus = "您現在用的版本已是最新的!";
    UpdateData(FALSE);
    m_buOK.EnableWindow(FALSE);
    return;
}

3. 偵測目標程式執行狀態並處理


DWORD CUpdateDlg::FindAppProcessID() {
    HANDLE hSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0);
    PROCESSENTRY32 pe; pe.dwSize = sizeof(pe);
    if (::Process32First(hSnap, &pe)) {
        do {
            CString name = pe.szExeFile;
            if (!name.CompareNoCase(m_strSoft + ".exe")) {
                ::CloseHandle(hSnap);
                return pe.th32ProcessID;
            }
        } while (::Process32Next(hSnap, &pe));
    }
    ::CloseHandle(hSnap);
    return -1;
}

若程式正在執行,提示使用者手動關閉或強制 TerminateProcess 結束。

4. 檔案下載與進度顯示


pFile->QueryInfo(HTTP_QUERY_CONTENT_LENGTH, str);  // 取得檔案大小
DWORD dwLen = atol(str);

// 先下載至 .upg 暫存檔,防止中斷損壞原檔
CStdioFile csf;
if (!csf.Open(str + ".upg",
    CFile::modeCreate | CFile::modeWrite | CFile::typeBinary | CFile::shareDenyWrite)) {
    AfxMessageBox("寫入檔案錯誤!檔案正在使用中,請先關閉程式!", MB_ICONSTOP);
    return FALSE;
}

char buf[2048]; DWORD dwRead = 0;
while ((n = pFile->Read(buf, sizeof(buf))) > 0) {
    dwRead += n;
    m_prog.SetPos(100 * dwRead / dwLen);  // 更新進度條
    // 處理訊息佇列保持介面回應
    MSG msg;
    for (int i = 0; i < 10; i++)
        if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
            TranslateMessage(&msg); DispatchMessage(&msg);
        }
    csf.Write(buf, n);
}
pFile->Close();

5. 原子性替換與完成


if (::DeleteFile(str)) {           // 刪除舊檔
    ::rename(str + ".upg", str);   // 重新命名新檔
    m_strStatus = strFile + "完成更新!";
    UpdateData(FALSE);
    // ...
}

更新設定檔格式 (update.ini)


[VolleyMail]
VERSION=3.1
FILE1=VolleyMail.exe
FILE2=SomeDll.dll
...

總結

採用 HTTP 下載、版本比對、進程檢測、暫存檔下載、原子替換機制,構建安全可靠的自動更新系統。完整細節請參考原始碼。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved