C++ 自动更新

#if !defined(ONLINE_UPDATER)
#define ONLINE_UPDATER
#if _MSC_VER > 1000
#pragma once
#endif
#include <Wininet.h>
#define LOCATION_UPDATE_FILE_CHECK _T("update.txt")
class OnlineUpdater
{
public:
OnlineUpdater();
virtual ~OnlineUpdater();
enum ErrorType
{
Success,
InternetConnectFailure,
InternetSessionFailure,
ConfigDownloadFailure,
FileDownloadFailure,
NoExecutableVersion,
UpdateNotRequired,
UpdateNotComplete
};
ErrorType CheckForUpdate(LPCTSTR UpdateServerURL);
HINTERNET GetSession(CString &URL);
bool InternetOkay();
bool DownloadConfig(HINTERNET hSession, BYTE *pBuf, DWORD bufSize);
bool DownloadFile(HINTERNET hSession, LPCTSTR localFile);
CString GetFileVersion(LPCTSTR file);
int CompareVersions(CString ver1, CString ver2);
bool IsDigits(CString text);
CString GetExecutable();
bool Switch(CString executable, CString update, bool WaitForReboot);
private:
HINTERNET hInternet;
};
#endif // !defined(ONLINE_UPDATER)
#include "stdafx.h"
#include "OnlineUpdater.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
#define TRANSFER_SIZE 4096
OnlineUpdater::OnlineUpdater()
{
hInternet = InternetOpen("AutoUpdateAgent", INTERNET_OPEN_TYPE_PRECONFIG,
NULL, NULL, 0);
}
OnlineUpdater::~OnlineUpdater()
{
if (hInternet)
{
InternetCloseHandle(hInternet);
}
}
OnlineUpdater::ErrorType OnlineUpdater::CheckForUpdate(LPCTSTR UpdateServerURL)
{
if (!InternetOkay())
{
return InternetConnectFailure;
}
bool bTransferSuccess = false;
CString URL = UpdateServerURL + CString(LOCATION_UPDATE_FILE_CHECK);
HINTERNET hSession = GetSession(URL);
if (!hSession)
{
return InternetSessionFailure;
}
BYTE pBuf[TRANSFER_SIZE];
memset(pBuf, NULL, sizeof(pBuf));
bTransferSuccess = DownloadConfig(hSession, pBuf, TRANSFER_SIZE);
InternetCloseHandle(hSession);
if (!bTransferSuccess)
{
return ConfigDownloadFailure;
}
CString executable = GetExecutable();
CString fileVersion = GetFileVersion(executable);
if (fileVersion.IsEmpty())
{
return NoExecutableVersion;
}
CString updateVersion = (char *) pBuf;
if (CompareVersions(updateVersion, fileVersion) != 1)
{
return UpdateNotRequired;
}
TCHAR path[MAX_PATH];
GetTempPath(MAX_PATH, path);
CString exeName = executable.Mid(1 + executable.ReverseFind(_T('\\')));
CString directory = path;
URL = UpdateServerURL + exeName;
hSession = GetSession(URL);
if (!hSession)
{
return InternetSessionFailure;
}
CString msg;
msg.Format(_T("An update of %s is now available. Proceed with the update?"),
exeName);
if (IDNO
== MessageBox(GetActiveWindow(), msg, _T("Update is available"),
MB_YESNO | MB_ICONQUESTION))
{
return UpdateNotComplete;
}
CString updateFileLocation = directory + exeName;
bTransferSuccess = DownloadFile(hSession, updateFileLocation);
InternetCloseHandle(hSession);
if (!bTransferSuccess)
{
return FileDownloadFailure;
}
if (!Switch(executable, updateFileLocation, false))
{
return UpdateNotComplete;
}
return Success;
}
bool OnlineUpdater::InternetOkay()
{
if (hInternet == NULL)
{
return false;
}
DWORD dwType;
if (!InternetGetConnectedState(&dwType, 0))
{
return false;
}
return true;
}
HINTERNET OnlineUpdater::GetSession(CString &URL)
{
TCHAR canonicalURL[1024];
DWORD nSize = 1024;
InternetCanonicalizeUrl(URL, canonicalURL, &nSize, ICU_BROWSER_MODE);
DWORD options = INTERNET_FLAG_NEED_FILE | INTERNET_FLAG_HYPERLINK
| INTERNET_FLAG_RESYNCHRONIZE | INTERNET_FLAG_RELOAD;
HINTERNET hSession = InternetOpenUrl(hInternet, canonicalURL, NULL, NULL,
options, 0);
URL = canonicalURL;
return hSession;
}
bool OnlineUpdater::DownloadConfig(HINTERNET hSession, BYTE *pBuf,
DWORD bufSize)
{
DWORD dwReadSizeOut;
InternetReadFile(hSession, pBuf, bufSize, &dwReadSizeOut);
if (dwReadSizeOut <= 0)
{
return false;
}
return true;
}
bool OnlineUpdater::DownloadFile(HINTERNET hSession, LPCTSTR localFile)
{
HANDLE hFile;
BYTE pBuf[TRANSFER_SIZE];
DWORD dwReadSizeOut, dwTotalReadSize = 0;
hFile = CreateFile(localFile, GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
return false;
do
{
DWORD dwWriteSize, dwNumWritten;
BOOL bRead = InternetReadFile(hSession, pBuf, TRANSFER_SIZE,
&dwReadSizeOut);
dwWriteSize = dwReadSizeOut;
if (bRead && dwReadSizeOut > 0)
{
dwTotalReadSize += dwReadSizeOut;
WriteFile(hFile, pBuf, dwWriteSize, &dwNumWritten, NULL);
if (dwWriteSize != dwNumWritten)
{
CloseHandle(hFile);
return false;
}
}
else
{
if (!bRead)
{
CloseHandle(hFile);
return false;
}
break;
}
} while (1);
CloseHandle(hFile);
return true;
}
CString OnlineUpdater::GetFileVersion(LPCTSTR file)
{
CString version;
VS_FIXEDFILEINFO *pVerInfo = NULL;
DWORD dwTemp, dwSize, dwHandle = 0;
BYTE *pData = NULL;
UINT uLen;
try
{
dwSize = GetFileVersionInfoSize((LPTSTR) file, &dwTemp);
if (dwSize == 0)
throw 1;
pData = new BYTE[dwSize];
if (pData == NULL)
throw 1;
if (!GetFileVersionInfo((LPTSTR) file, dwHandle, dwSize, pData))
throw 1;
if (!VerQueryValue(pData, _T("\\"), (void **) &pVerInfo, &uLen))
throw 1;
DWORD verMS = pVerInfo->dwFileVersionMS;
DWORD verLS = pVerInfo->dwFileVersionLS;
int ver[4];
ver[0] = HIWORD(verMS);
ver[1] = LOWORD(verMS);
ver[2] = HIWORD(verLS);
ver[3] = LOWORD(verLS);
// Are lo-words used?
if (ver[2] != 0 || ver[3] != 0)
{
version.Format(_T("%d.%d.%d.%d"), ver[0], ver[1], ver[2], ver[3]);
}
else if (ver[0] != 0 || ver[1] != 0)
{
version.Format(_T("%d.%d"), ver[0], ver[1]);
}
delete pData;
return version;
} catch (...)
{
return _T("");
}
}
int OnlineUpdater::CompareVersions(CString ver1, CString ver2)
{
int wVer1[4], wVer2[4];
int i;
TCHAR *pVer1 = ver1.GetBuffer(256);
TCHAR *pVer2 = ver2.GetBuffer(256);
for (i = 0; i < 4; i++)
{
wVer1[i] = 0;
wVer2[i] = 0;
}
TCHAR *pToken = strtok(pVer1, _T("."));
if (pToken == NULL)
{
return -21;
}
i = 3;
while (pToken != NULL)
{
if (i < 0 || !IsDigits(pToken))
{
return -21;
}
wVer1[i] = atoi(pToken);
pToken = strtok(NULL, _T("."));
i--;
}
ver1.ReleaseBuffer();
pToken = strtok(pVer2, _T("."));
if (pToken == NULL)
{
return -22;
}
i = 3;
while (pToken != NULL)
{
if (i < 0 || !IsDigits(pToken))
{
return -22;
}
wVer2[i] = atoi(pToken);
pToken = strtok(NULL, _T("."));
i--;
}
ver2.ReleaseBuffer();
for (i = 3; i >= 0; i--)
{
if (wVer1[i] > wVer2[i])
{
return 1;
}
else if (wVer1[i] < wVer2[i])
{
return -1;
}
}
return 0;
}
bool OnlineUpdater::IsDigits(CString text)
{
for (int i = 0; i < text.GetLength(); i++)
{
TCHAR c = text.GetAt(i);
if (c >= _T('0') && c <= _T('9'))
{
}
else
{
return false;
}
}
return true;
}
CString OnlineUpdater::GetExecutable()
{
HMODULE hModule = ::GetModuleHandle(NULL);
ASSERT(hModule != 0);
TCHAR path[MAX_PATH];
VERIFY(::GetModuleFileName(hModule, path, MAX_PATH));
return path;
}
bool OnlineUpdater::Switch(CString executable, CString update,
bool WaitForReboot)
{
int type =
(WaitForReboot) ?
MOVEFILE_DELAY_UNTIL_REBOOT : MOVEFILE_COPY_ALLOWED;
const TCHAR *backup = _T("OldExecutable.bak");
CString directory = executable.Left(executable.ReverseFind(_T('\\')));
CString backupFile = directory + _T('\\') + CString(backup);
DeleteFile(backupFile);
if (!MoveFileEx(executable, backupFile, type))
{
return false;
}
BOOL bMoveOK = (MoveFileEx(update, executable, type) == TRUE);
int i = GetLastError();
return bMoveOK;
}
 (2015年05月16
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值