避免啟動時強制彈出「是否更新」對話框干擾使用者。採用「靜默檢查 → 發現新版本顯示超連結 → 使用者自主決定」的友善模式。
4,3,0,0) 以文字檔 (version.txt) 放置 FTP 伺服器。VS_VERSION_INFO 資源比對,新版本時於介面顯示「更新版本 x.xx」連結。HINTERNET hInternet = InternetOpen(...);
HINTERNET hFtp = InternetConnect(hInternet, server, INTERNET_DEFAULT_FTP_PORT, user, pass, INTERNET_SERVICE_FTP, 0, 0);
HINTERNET hFile = FtpOpenFile(hFtp, "version.txt", GENERIC_READ, FTP_TRANSFER_TYPE_ASCII, 0);
InternetReadFile(hFile, buffer, size, &dwRead);
class CWebVersion {
protected:
enum { BUFSIZE = 64 };
LPCTSTR m_lpServer;
DWORD m_dwError;
TCHAR m_errInfo[256];
TCHAR m_version[BUFSIZE];
void SaveErrorInfo();
public:
DWORD dwVersionMS, dwVersionLS; // 64-bit 版本號拆為高低 32 位
CWebVersion(LPCTSTR server) : m_lpServer(server) {}
static BOOL Online(); // 檢查網路連線
BOOL ReadVersion(LPCTSTR file, LPCSTR user, LPCSTR pass);
LPCTSTR GetVersionText() { return m_version; }
DWORD GetError() { return m_dwError; }
LPCTSTR GetExtendedErrorInfo() { return m_errInfo; }
};
BOOL CWebVersion::Online() {
DWORD dwState = 0, dwSize = sizeof(DWORD);
return InternetQueryOption(NULL, INTERNET_OPTION_CONNECTED_STATE, &dwState, &dwSize)
&& (dwState & INTERNET_STATE_CONNECTED);
}
BOOL CWebVersion::ReadVersion(LPCTSTR lpFileName, LPCSTR user, LPCSTR pass) {
CInternetHandle hInternet, hFtpSession, hFtpFile;
m_version[0] = 0; m_dwError = 0; m_errInfo[0] = 0;
DWORD nRead = 0;
hInternet = InternetOpen(NULL, INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
if (hInternet) {
hFtpSession = InternetConnect(hInternet, m_lpServer, INTERNET_DEFAULT_FTP_PORT,
user, pass, INTERNET_SERVICE_FTP, 0, NULL);
if (hFtpSession) {
hFtpFile = FtpOpenFile(hFtpSession, lpFileName, GENERIC_READ,
FTP_TRANSFER_TYPE_ASCII, NULL);
if (hFtpFile) {
InternetReadFile(hFtpFile, m_version, BUFSIZE, &nRead);
if (nRead > 0) {
m_version[nRead] = 0;
int Mhi, Mlo, mhi, mlo;
_stscanf(m_version, "%x,%x,%x,%x", &Mhi, &Mlo, &mhi, &mlo);
dwVersionMS = MAKELONG(Mlo, Mhi);
dwVersionLS = MAKELONG(mlo, mhi);
return TRUE;
}
}
}
}
m_dwError = GetLastError();
if (m_dwError == ERROR_INTERNET_EXTENDED_ERROR) {
DWORD dwErr, len = _countof(m_errInfo);
InternetGetLastResponseInfo(&dwErr, m_errInfo, &len);
}
return FALSE;
}
class CInternetHandle {
HINTERNET m_handle;
public:
CInternetHandle() : m_handle(NULL) {}
CInternetHandle(HINTERNET h) : m_handle(h) {}
~CInternetHandle() { Close(); }
void Close() { if (m_handle) { InternetCloseHandle(m_handle); m_handle = NULL; } }
CInternetHandle& operator=(HINTERNET h) { ASSERT(m_handle==NULL); m_handle=h; return *this; }
operator HINTERNET() { return m_handle; }
};
解決 InternetCloseHandle 清除錯誤碼導致 GetLastError 失效的問題,簡化錯誤處理流程。
if (CWebVersion::Online()) {
CWebVersion ver(_T("pub.chinafsdu.net"));
if (ver.ReadVersion(_T("version.txt"), _T("pub"), _T("pub")))
m_dwNewVersion = ver.dwVersionMS; // 僅比較高 32 位示範
}
CMyVersionInfo vi; // 取得本地 VS_VERSION_INFO
if (m_dwNewVersion && vi.dwProductVersionMS < m_dwNewVersion) {
CString s; s.Format(_T("更新版本 %d.%02d"), HIWORD(m_dwNewVersion), LOWORD(m_dwNewVersion));
m_wndVerChkLink.SetWindowText(s);
} else {
m_wndVerChkLink.ShowWindow(SW_HIDE);
}
FTP 下載 10 字節通常極快,但受伺服器位置/負載影響可能有明顯延遲。建議放入背景執行緒執行 ReadVersion,避免阻塞 UI 啟動。
封裝 GetFileVersionInfo/VerQueryValue 解析 VS_VERSION_INFO 取得 dwProductVersionMS/LS,程式碼見原文附件。