 Issue 10920006:
  Expect MSI installers  (Closed)
    
  
    Issue 10920006:
  Expect MSI installers  (Closed) 
  | Left: | ||
| Right: | 
| OLD | NEW | 
|---|---|
| 1 #include <functional> | 1 #include <functional> | 
| 2 #include <memory> | 2 #include <memory> | 
| 3 #include <sstream> | 3 #include <sstream> | 
| 4 | |
| 5 #include <Windows.h> | |
| 6 #include <Msi.h> | |
| 7 | |
| 4 #include <AdblockPlus/FileSystem.h> | 8 #include <AdblockPlus/FileSystem.h> | 
| 5 #include <AdblockPlus/WebRequest.h> | 9 #include <AdblockPlus/WebRequest.h> | 
| 6 | 10 | 
| 7 #include "../shared/Dictionary.h" | 11 #include "../shared/Dictionary.h" | 
| 8 #include "../shared/Utils.h" | 12 #include "../shared/Utils.h" | 
| 9 #include "Debug.h" | 13 #include "Debug.h" | 
| 10 #include "Resource.h" | 14 #include "Resource.h" | 
| 11 #include "Updater.h" | 15 #include "Updater.h" | 
| 12 | 16 | 
| 13 namespace | 17 namespace | 
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 77 | 81 | 
| 78 DWORD RunThread(LPVOID param) | 82 DWORD RunThread(LPVOID param) | 
| 79 { | 83 { | 
| 80 std::auto_ptr<ThreadCallbackType> callback(reinterpret_cast<ThreadCallbackTy pe*>(param)); | 84 std::auto_ptr<ThreadCallbackType> callback(reinterpret_cast<ThreadCallbackTy pe*>(param)); | 
| 81 (*callback)(); | 85 (*callback)(); | 
| 82 return 0; | 86 return 0; | 
| 83 } | 87 } | 
| 84 } | 88 } | 
| 85 | 89 | 
| 86 Updater::Updater(AdblockPlus::JsEnginePtr jsEngine, const std::string& url) | 90 Updater::Updater(AdblockPlus::JsEnginePtr jsEngine, const std::string& url) | 
| 87 : jsEngine(jsEngine), url(url), tempFile(GetAppDataPath() + L"\\update.exe") | 91 : jsEngine(jsEngine), url(url), tempFile(GetAppDataPath() + L"\\update.msi") | 
| 88 { | 92 { | 
| 89 } | 93 } | 
| 90 | 94 | 
| 91 void Updater::Update() | 95 void Updater::Update() | 
| 92 { | 96 { | 
| 93 Debug("Update available: " + url); | 97 Debug("Update available: " + url); | 
| 94 | 98 | 
| 95 if (DialogBox(NULL, MAKEINTRESOURCE(IDD_UPDATEDIALOG), GetDesktopWindow(), | 99 if (DialogBox(NULL, MAKEINTRESOURCE(IDD_UPDATEDIALOG), GetDesktopWindow(), | 
| 96 reinterpret_cast<DLGPROC>(&UpdateDlgProc)) == IDOK) | 100 reinterpret_cast<DLGPROC>(&UpdateDlgProc)) == IDOK) | 
| 97 { | 101 { | 
| 98 Debug("User accepted update"); | 102 Debug("User accepted update"); | 
| 99 | 103 | 
| 100 DialogCallbackType* callback = new DialogCallbackType(std::bind(&Updater::St artDownload, | |
| 101 this, std::placeholders::_1)); | |
| 102 int result = DialogBoxParam(NULL, MAKEINTRESOURCE(IDD_DOWNLOADDIALOG), GetDe sktopWindow(), | |
| 103 reinterpret_cast<DLGPROC>(&DownloadDlgProc), | |
| 104 reinterpret_cast<LPARAM>(callback)); | |
| 105 if (result == DOWNLOAD_FAILED) | |
| 106 { | 104 { | 
| 
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
 | |
| 107 Dictionary* dict = Dictionary::GetInstance(); | 105 DialogCallbackType* callback = new DialogCallbackType(std::bind(&Updater:: StartDownload, | 
| 108 MessageBoxW(NULL, | 106 this, std::placeholders::_1)); | 
| 109 dict->Lookup("updater", "download-error-neterror").c_str(), | 107 int result = DialogBoxParam(NULL, MAKEINTRESOURCE(IDD_DOWNLOADDIALOG), Get DesktopWindow(), | 
| 110 dict->Lookup("updater", "download-error-title").c_str(), | 108 reinterpret_cast<DLGPROC>(&DownloadDlgProc), | 
| 111 0); | 109 reinterpret_cast<LPARAM>(callback)); | 
| 110 if (result == DOWNLOAD_FAILED) | |
| 111 { | |
| 112 Dictionary* dict = Dictionary::GetInstance(); | |
| 113 MessageBoxW(NULL, | |
| 114 dict->Lookup("updater", "download-error-neterror").c_str(), | |
| 115 dict->Lookup("updater", "download-error-title").c_str(), | |
| 116 0); | |
| 117 } | |
| 118 if (result != IDOK) | |
| 119 return; | |
| 112 } | 120 } | 
| 113 if (result != IDOK) | |
| 114 return; | |
| 115 | 121 | 
| 116 PROCESS_INFORMATION pi; | 122 { | 
| 117 STARTUPINFO si; | 123 UINT result = ::MsiInstallProductW(tempFile.c_str(), L"ACTION=INSTALL INST ALLUILEVEL=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 :)
 | |
| 118 ::ZeroMemory(&si, sizeof(si)); | 124 if (result != ERROR_SUCCESS) | 
| 119 si.cb = sizeof(si); | 125 { | 
| 120 si.wShowWindow = FALSE; | 126 Dictionary* dict = Dictionary::GetInstance(); | 
| 127 std::wstringstream message; | |
| 128 message << dict->Lookup("updater", "download-error-runerror"); | |
| 129 message << std::endl << L"(error " << result << L")"; | |
| 130 MessageBoxW(NULL, | |
| 131 message.str().c_str(), | |
| 132 dict->Lookup("updater", "download-error-title").c_str(), | |
| 133 0); | |
| 121 | 134 | 
| 122 if (!::CreateProcessW(tempFile.c_str(), NULL, NULL, NULL, FALSE, CREATE_BREA KAWAY_FROM_JOB, NULL, NULL, &si, &pi)) | 135 std::stringstream error; | 
| 123 { | 136 error << "Installing update failed (error " << result << ")"; | 
| 124 Dictionary* dict = Dictionary::GetInstance(); | 137 Debug(error.str()); | 
| 125 MessageBoxW(NULL, | 138 return; | 
| 126 dict->Lookup("updater", "download-error-runerror").c_str(), | 139 } | 
| 127 dict->Lookup("updater", "download-error-title").c_str(), | |
| 128 0); | |
| 129 DebugLastError("Creating updater process failed"); | |
| 130 return; | |
| 131 } | 140 } | 
| 132 ::CloseHandle(pi.hProcess); | |
| 133 ::CloseHandle(pi.hThread); | |
| 134 } | 141 } | 
| 135 } | 142 } | 
| 136 | 143 | 
| 137 void Updater::StartDownload(HWND dialog) | 144 void Updater::StartDownload(HWND dialog) | 
| 138 { | 145 { | 
| 139 this->dialog = dialog; | 146 this->dialog = dialog; | 
| 140 ThreadCallbackType* callback = new ThreadCallbackType(std::bind(&Updater::RunD ownload, this)); | 147 ThreadCallbackType* callback = new ThreadCallbackType(std::bind(&Updater::RunD ownload, this)); | 
| 141 ::CreateThread(NULL, 0, reinterpret_cast<LPTHREAD_START_ROUTINE>(&RunThread), | 148 ::CreateThread(NULL, 0, reinterpret_cast<LPTHREAD_START_ROUTINE>(&RunThread), | 
| 142 callback, 0, NULL); | 149 callback, 0, NULL); | 
| 143 } | 150 } | 
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 175 } | 182 } | 
| 176 catch (const std::exception& e) | 183 catch (const std::exception& e) | 
| 177 { | 184 { | 
| 178 DebugException(e); | 185 DebugException(e); | 
| 179 EndDialog(dialog, DOWNLOAD_FAILED); | 186 EndDialog(dialog, DOWNLOAD_FAILED); | 
| 180 return; | 187 return; | 
| 181 } | 188 } | 
| 182 | 189 | 
| 183 EndDialog(dialog, IDOK); | 190 EndDialog(dialog, IDOK); | 
| 184 } | 191 } | 
| OLD | NEW |