preface

I have searched many versions of electron software on the Internet, but I don’t quite understand them. And myself is also engaged in c++, so make a native upgrade software is not a small matter. Simply use VS2017 + Duilib to write an upgrade software.

logic

This upgrade software logic is simple, the user actually opens first is to upgrade the software, open the software upgrade software will be the url configuration upgrade software and local versions of the software, at the same time on the server side, also can put a zip format upgrade packages and a named version. The json file, which records the package in the software version number.

If the upgrade software detects that the local version is smaller than the version on the server, it downloads the zip package to the local PC, decompresses it to the specified directory according to the Settings in setting.ini, and then opens the application program in the specified directory.

code

int CFirstpage::StartMain(a)
{
	GetSettingIni(a); : :DeleteFile(string(GetAppPath(NULL) + "/unzip/version.json").c_str()); : :DeleteFile(string(GetAppPath(NULL) + "/unzip/zip.zip").c_str());
	label_show->SetText(_T("Checking the file directory..."));
	// 0 Check the directory
	CUnzipper unzipper;
	unzipper.CreateFolder(string(GetAppPath(NULL) + "/unzip/").c_str());
	// 0-1 Clear the directory
	label_show->SetText(_T("Checking local version..."));
	//1. Obtain the local information server address and local version
	GetLocalInfo(m_strVersionLocal, m_strCity, m_strPlatformUrl);
	sVersionFileName = string(DST_VERSION_JSON) + "version_" + m_strCity + ".json";
	
	m_strVersionDown = GetAppPath(NULL) + "\\unzip\\version.json";
	label_show->SetText(_T("Downloading file update list..."));
	//2. Download the remote version file
	HANDLE hThread = CreateThread(NULL.0, DownloadThread, this.0.NULL);
	CloseHandle(hThread);

	return 0;
}
Copy the code

Use the libcurl library to download the compressed server package and display the progress


static size_t DownloadCallback(void* pBuffer, size_t nSize, size_t nMemByte, void* pParam)
{
	// Append the downloaded data to the file (must have a, otherwise the previous writing will be overwritten)
	FILE* fp = NULL;
	fopen_s(&fp, g_pFirstpage->m_strVersionDown.c_str(), "ab+");
	size_t nWrite = fwrite(pBuffer, nSize, nMemByte, fp);
	fclose(fp);
	return nWrite;
}

bool gDownload_json = false;
bool gDownload_zip = false;

static int ProgressCallback(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow)
{
	if (dltotal > 0.1 && dltotal < 0.1)
		return 0;
	int nPos = (int)((dlnow / dltotal) * 100);
	// Notify the progress bar to update the download progress
	//::PostMessage(g_pFirstpage->GetHWND(), WM_PROGRESS_UPDATE, nPos, 0);
	//::Sleep(10);
	if (nPos >= 100) 
	{
		if(! gDownload_json) { gDownload_json =true; : :Sleep(500); : :PostMessage(g_pFirstpage->GetHWND(), WM_DOWNLOAD_ZIP, nPos, 0); }}return 0;
}

static size_t DownloadCallbackZip(void* pBuffer, size_t nSize, size_t nMemByte, void* pParam)
{
	// Append the downloaded data to the file (must have a, otherwise the previous writing will be overwritten)
	FILE* fp = NULL;
	fopen_s(&fp, g_pFirstpage->m_strZipDown.c_str(), "ab+");
	size_t nWrite = fwrite(pBuffer, nSize, nMemByte, fp);
	fclose(fp);
	return nWrite;
}

static int ProgressCallbackZip(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow)
{
	if (dltotal > 0.1 && dltotal < 0.1)
		return 0;
	int nPos = (int)((dlnow / dltotal) * 100);
	// Notify the progress bar to update the download progress: :SendMessage(g_pFirstpage->GetHWND(), WM_PROGRESS_UPDATE, nPos, 0); : :Sleep(10);
	if (nPos >= 100)
	{
		if(! gDownload_zip) { gDownload_zip =true; : :Sleep(500); : :SendMessage(g_pFirstpage->GetHWND(), WM_UNZIP, nPos, 0); }}return 0;
}

DWORD WINAPI DownloadThread(LPVOID lpParam)
{
	CFirstpage* pFirstpage = (CFirstpage*)lpParam;
	//Sleep(10000);
	// initialize curl, which is required
	CURL* curl = curl_easy_init(a);curl_easy_setopt(curl, CURLOPT_URL, string(pFirstpage->m_strPlatformUrl+ sVersionFileName).c_str());
	// Set the callback for received data
	curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, DownloadCallback);
	// Set the maximum number of redirects
	curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 5);
	// Set the 301 and 302 jumps to follow location
	curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
	curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);
	curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, 7777);
	// Set the progress callback function
	curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, ProgressCallback);
	if (pFirstpage->m_bIsProxy)
	{
		curl_easy_setopt(curl, CURLOPT_PROXYAUTH, CURLAUTH_BASIC); // Proxy authentication mode
		curl_easy_setopt(curl, CURLOPT_PROXY, pFirstpage->m_strProxyIp.c_str()); // Proxy server address
		curl_easy_setopt(curl, CURLOPT_PROXYPORT, pFirstpage->m_nProxyPort); // Proxy server port
		curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_HTTP); // Use HTTP proxy mode
	}

	// Start executing the request
	CURLcode retcCode = curl_easy_perform(curl);
	// Check for error messages
	const char* pError = curl_easy_strerror(retcCode);
	// Clear the curl to match the previous initialization
	curl_easy_cleanup(curl);
	if(retcCode ! = CURLE_OK) { pFirstpage->label_show->SetText(pError);
		Sleep(1000);
		pFirstpage->deq_Msg.push_back(_T("StartExe"));
	}

	return 0;
}



DWORD WINAPI DownloadThreadZip(LPVOID lpParam)
{
	CFirstpage* pFirstpage = (CFirstpage*)lpParam;
	//Sleep(10000);
	// initialize curl, which is required
	CURL* curl = curl_easy_init(a);curl_easy_setopt(curl, CURLOPT_URL, string(pFirstpage->m_strPlatformUrl + DST_VERSION_PATH + sZipFileName).c_str());
	// Set the callback for received data
	curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, DownloadCallbackZip);
	// Set the maximum number of redirects
	curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 5);
	// Set the 301 and 302 jumps to follow location
	curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
	curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);
	// Set the progress callback function
	curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, ProgressCallbackZip);
	if (pFirstpage->m_bIsProxy)
	{
		curl_easy_setopt(curl, CURLOPT_PROXYAUTH, CURLAUTH_BASIC); // Proxy authentication mode
		curl_easy_setopt(curl, CURLOPT_PROXY, pFirstpage->m_strProxyIp.c_str()); // Proxy server address
		curl_easy_setopt(curl, CURLOPT_PROXYPORT, pFirstpage->m_nProxyPort); // Proxy server port
		curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_HTTP); // Use HTTP proxy mode
	}

	// Start executing the request
	CURLcode retcCode = curl_easy_perform(curl);
	// Check for error messages
	const char* pError = curl_easy_strerror(retcCode);
	// Clear the curl to match the previous initialization
	curl_easy_cleanup(curl);
	if(retcCode ! = CURLE_OK) { pFirstpage->label_show->SetText(pError);
		Sleep(1000);
		pFirstpage->deq_Msg.push_back(_T("StartExe"));
	}
	//p_mainWnd->Close();
	return 0;
}
Copy the code

run