| Index: src/engine/Updater.cpp |
| =================================================================== |
| --- a/src/engine/Updater.cpp |
| +++ b/src/engine/Updater.cpp |
| @@ -1,11 +1,15 @@ |
| #include <functional> |
| #include <memory> |
| #include <sstream> |
| + |
| +#include <Windows.h> |
| +#include <Msi.h> |
| + |
| #include <AdblockPlus/FileSystem.h> |
| #include <AdblockPlus/WebRequest.h> |
| #include "../shared/Dictionary.h" |
| #include "../shared/Utils.h" |
| #include "Debug.h" |
| #include "Resource.h" |
| #include "Updater.h" |
| @@ -79,63 +83,66 @@ namespace |
| { |
| std::auto_ptr<ThreadCallbackType> callback(reinterpret_cast<ThreadCallbackType*>(param)); |
| (*callback)(); |
| return 0; |
| } |
| } |
| Updater::Updater(AdblockPlus::JsEnginePtr jsEngine, const std::string& url) |
| - : jsEngine(jsEngine), url(url), tempFile(GetAppDataPath() + L"\\update.exe") |
| + : jsEngine(jsEngine), url(url), tempFile(GetAppDataPath() + L"\\update.msi") |
| { |
| } |
| void Updater::Update() |
| { |
| Debug("Update available: " + url); |
| if (DialogBox(NULL, MAKEINTRESOURCE(IDD_UPDATEDIALOG), GetDesktopWindow(), |
| reinterpret_cast<DLGPROC>(&UpdateDlgProc)) == IDOK) |
| { |
| Debug("User accepted update"); |
| - DialogCallbackType* callback = new DialogCallbackType(std::bind(&Updater::StartDownload, |
| - this, std::placeholders::_1)); |
| - int result = DialogBoxParam(NULL, MAKEINTRESOURCE(IDD_DOWNLOADDIALOG), GetDesktopWindow(), |
| - reinterpret_cast<DLGPROC>(&DownloadDlgProc), |
| - reinterpret_cast<LPARAM>(callback)); |
| - if (result == DOWNLOAD_FAILED) |
| { |
|
Felix Dahlke
2013/06/11 10:07:52
I presume the two blocks are to avoid conflicts be
Wladimir Palant
2013/06/11 14:42:10
I would rather have distinct scopes for these two
|
| - Dictionary* dict = Dictionary::GetInstance(); |
| - MessageBoxW(NULL, |
| - dict->Lookup("updater", "download-error-neterror").c_str(), |
| - dict->Lookup("updater", "download-error-title").c_str(), |
| - 0); |
| + DialogCallbackType* callback = new DialogCallbackType(std::bind(&Updater::StartDownload, |
| + this, std::placeholders::_1)); |
| + int result = DialogBoxParam(NULL, MAKEINTRESOURCE(IDD_DOWNLOADDIALOG), GetDesktopWindow(), |
| + reinterpret_cast<DLGPROC>(&DownloadDlgProc), |
| + reinterpret_cast<LPARAM>(callback)); |
| + if (result == DOWNLOAD_FAILED) |
| + { |
| + Dictionary* dict = Dictionary::GetInstance(); |
| + MessageBoxW(NULL, |
| + dict->Lookup("updater", "download-error-neterror").c_str(), |
| + dict->Lookup("updater", "download-error-title").c_str(), |
| + 0); |
| + } |
| + if (result != IDOK) |
| + return; |
| } |
| - if (result != IDOK) |
| - return; |
| - PROCESS_INFORMATION pi; |
| - STARTUPINFO si; |
| - ::ZeroMemory(&si, sizeof(si)); |
| - si.cb = sizeof(si); |
| - si.wShowWindow = FALSE; |
| + { |
| + UINT result = ::MsiInstallProductW(tempFile.c_str(), L"ACTION=INSTALL INSTALLUILEVEL=2"); |
|
Oleksandr
2013/06/10 16:47:56
Wouldn't it be better just to launch like "msiexec
Wladimir Palant
2013/06/11 04:29:56
MsiInstallProduct is IMHO a much cleaner solution
Felix Dahlke
2013/06/11 10:07:52
As long as "update.msi" is hardcoded above we'd ne
Oleksandr
2013/06/11 10:24:49
That's my point. Stuff happens, and maybe for some
Felix Dahlke
2013/06/11 10:28:05
Couldn't we just ship an exe with the msi and exec
Wladimir Palant
2013/06/11 14:42:10
I really don't see why we would need a plan b (one
Felix Dahlke
2013/06/12 13:03:40
I'd vote for two functions then :)
|
| + if (result != ERROR_SUCCESS) |
| + { |
| + Dictionary* dict = Dictionary::GetInstance(); |
| + std::wstringstream message; |
| + message << dict->Lookup("updater", "download-error-runerror"); |
| + message << std::endl << L"(error " << result << L")"; |
| + MessageBoxW(NULL, |
| + message.str().c_str(), |
| + dict->Lookup("updater", "download-error-title").c_str(), |
| + 0); |
| - if (!::CreateProcessW(tempFile.c_str(), NULL, NULL, NULL, FALSE, CREATE_BREAKAWAY_FROM_JOB, NULL, NULL, &si, &pi)) |
| - { |
| - Dictionary* dict = Dictionary::GetInstance(); |
| - MessageBoxW(NULL, |
| - dict->Lookup("updater", "download-error-runerror").c_str(), |
| - dict->Lookup("updater", "download-error-title").c_str(), |
| - 0); |
| - DebugLastError("Creating updater process failed"); |
| - return; |
| + std::stringstream error; |
| + error << "Installing update failed (error " << result << ")"; |
| + Debug(error.str()); |
| + return; |
| + } |
| } |
| - ::CloseHandle(pi.hProcess); |
| - ::CloseHandle(pi.hThread); |
| } |
| } |
| void Updater::StartDownload(HWND dialog) |
| { |
| this->dialog = dialog; |
| ThreadCallbackType* callback = new ThreadCallbackType(std::bind(&Updater::RunDownload, this)); |
| ::CreateThread(NULL, 0, reinterpret_cast<LPTHREAD_START_ROUTINE>(&RunThread), |