Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Unified Diff: src/engine/Updater.cpp

Issue 10920006: Expect MSI installers (Closed)
Patch Set: Created June 10, 2013, 3:27 p.m.
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
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),

Powered by Google App Engine
This is Rietveld