Skip to content
Permalink
Browse files

Merge pull request #8217 from CookiePLMonster/windows-updater-improve…

…ments

Updates to auto-updater on Windows
  • Loading branch information
stenzek committed Jul 23, 2019
2 parents 66e7a11 + baab660 commit 8f6b237e119b5bfb1317cb36b6fac6c71245b4f0
@@ -95,6 +95,11 @@ void Updater::OnUpdateAvailable(const NewVersionInformation& info)
AutoUpdateChecker::RestartMode::RESTART_AFTER_UPDATE); AutoUpdateChecker::RestartMode::RESTART_AFTER_UPDATE);


if (!later) if (!later)
m_parent->close(); {
RunOnObject(m_parent, [this] {
m_parent->close();
return 0;
});
}
} }
} }
@@ -234,12 +234,16 @@ void AutoUpdateChecker::TriggerUpdate(const AutoUpdateChecker::NewVersionInforma
INFO_LOG(COMMON, "Updater command line: %s", command_line.c_str()); INFO_LOG(COMMON, "Updater command line: %s", command_line.c_str());


#ifdef _WIN32 #ifdef _WIN32
STARTUPINFO sinfo = {sizeof(info)}; STARTUPINFO sinfo = {sizeof(sinfo)};
sinfo.dwFlags = STARTF_FORCEOFFFEEDBACK; // No hourglass cursor after starting the process. sinfo.dwFlags = STARTF_FORCEOFFFEEDBACK; // No hourglass cursor after starting the process.
PROCESS_INFORMATION pinfo; PROCESS_INFORMATION pinfo;
if (!CreateProcessW(UTF8ToUTF16(reloc_updater_path).c_str(), if (CreateProcessW(UTF8ToUTF16(reloc_updater_path).c_str(), UTF8ToUTF16(command_line).data(),
const_cast<wchar_t*>(UTF8ToUTF16(command_line).c_str()), nullptr, nullptr, nullptr, nullptr, FALSE, 0, nullptr, nullptr, &sinfo, &pinfo))
FALSE, 0, nullptr, nullptr, &sinfo, &pinfo)) {
CloseHandle(pinfo.hThread);
CloseHandle(pinfo.hProcess);
}
else
{ {
ERROR_LOG(COMMON, "Could not start updater process: error=%d", GetLastError()); ERROR_LOG(COMMON, "Could not start updater process: error=%d", GetLastError());
} }
@@ -16,6 +16,7 @@
#include "Common/CommonPaths.h" #include "Common/CommonPaths.h"
#include "Common/FileUtil.h" #include "Common/FileUtil.h"
#include "Common/HttpRequest.h" #include "Common/HttpRequest.h"
#include "Common/ScopeGuard.h"
#include "Common/StringUtil.h" #include "Common/StringUtil.h"
#include "UpdaterCommon/UI.h" #include "UpdaterCommon/UI.h"


@@ -498,7 +499,6 @@ void FatalError(const std::string& message)


UI::SetVisible(true); UI::SetVisible(true);
UI::Error(message); UI::Error(message);
UI::Stop();
} }


std::optional<Manifest> ParseManifest(const std::string& manifest) std::optional<Manifest> ParseManifest(const std::string& manifest)
@@ -686,6 +686,7 @@ bool RunUpdater(std::vector<std::string> args)
UI::Init(); UI::Init();
UI::SetVisible(false); UI::SetVisible(false);


Common::ScopeGuard ui_guard{[] { UI::Stop(); }};
Options opts = std::move(*maybe_opts); Options opts = std::move(*maybe_opts);


if (opts.log_file) if (opts.log_file)
@@ -777,7 +778,5 @@ bool RunUpdater(std::vector<std::string> args)
UI::LaunchApplication(opts.binary_to_restart.value()); UI::LaunchApplication(opts.binary_to_restart.value());
} }


UI::Stop();

return true; return true;
} }
@@ -6,6 +6,7 @@
#include <ShlObj.h> #include <ShlObj.h>
#include <shellapi.h> #include <shellapi.h>


#include <optional>
#include <string> #include <string>
#include <vector> #include <vector>


@@ -32,6 +33,28 @@ std::vector<std::string> CommandLineToUtf8Argv(PCWSTR command_line)
LocalFree(tokenized); LocalFree(tokenized);
return argv; return argv;
} }

std::optional<std::wstring> GetModuleName(HINSTANCE hInstance)
{
std::wstring name;
DWORD max_size = 50; // Start with space for 50 characters and grow if needed
name.resize(max_size);

DWORD size;
while ((size = GetModuleFileNameW(hInstance, name.data(), max_size)) == max_size &&
GetLastError() == ERROR_INSUFFICIENT_BUFFER)
{
max_size *= 2;
name.resize(max_size);
}

if (size == 0)
{
return {};
}
name.resize(size);
return name;
}
}; // namespace }; // namespace


int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow) int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow)
@@ -64,15 +87,15 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine
return 1; return 1;
} }


wchar_t path[MAX_PATH]; auto path = GetModuleName(hInstance);
if (GetModuleFileName(hInstance, path, sizeof(path)) == 0) if (!path)
{ {
MessageBox(nullptr, L"Failed to get updater filename.", L"Error", MB_ICONERROR); MessageBox(nullptr, L"Failed to get updater filename.", L"Error", MB_ICONERROR);
return 1; return 1;
} }


// Relaunch the updater as administrator // Relaunch the updater as administrator
ShellExecuteW(nullptr, L"runas", path, pCmdLine, NULL, SW_SHOW); ShellExecuteW(nullptr, L"runas", path->c_str(), pCmdLine, NULL, SW_SHOW);
return 0; return 0;
} }


@@ -12,7 +12,6 @@
#include <ShObjIdl.h> #include <ShObjIdl.h>
#include <shellapi.h> #include <shellapi.h>


#include "Common/Flag.h"
#include "Common/StringUtil.h" #include "Common/StringUtil.h"


namespace namespace
@@ -23,8 +22,7 @@ HWND total_progressbar_handle = nullptr;
HWND current_progressbar_handle = nullptr; HWND current_progressbar_handle = nullptr;
ITaskbarList3* taskbar_list = nullptr; ITaskbarList3* taskbar_list = nullptr;


Common::Flag running; std::thread ui_thread;
Common::Flag request_stop;


int GetWindowHeight(HWND hwnd) int GetWindowHeight(HWND hwnd)
{ {
@@ -33,6 +31,17 @@ int GetWindowHeight(HWND hwnd)


return rect.bottom - rect.top; return rect.bottom - rect.top;
} }

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
}; // namespace }; // namespace


constexpr int PROGRESSBAR_FLAGS = WS_VISIBLE | WS_CHILD | PBS_SMOOTH | PBS_SMOOTHREVERSE; constexpr int PROGRESSBAR_FLAGS = WS_VISIBLE | WS_CHILD | PBS_SMOOTH | PBS_SMOOTHREVERSE;
@@ -46,7 +55,7 @@ bool InitWindow()
InitCommonControls(); InitCommonControls();


WNDCLASS wndcl = {}; WNDCLASS wndcl = {};
wndcl.lpfnWndProc = DefWindowProcW; wndcl.lpfnWndProc = WindowProc;
wndcl.hbrBackground = GetSysColorBrush(COLOR_MENU); wndcl.hbrBackground = GetSysColorBrush(COLOR_MENU);
wndcl.lpszClassName = L"UPDATER"; wndcl.lpszClassName = L"UPDATER";


@@ -124,14 +133,6 @@ bool InitWindow()
return true; return true;
} }


void Destroy()
{
DestroyWindow(window_handle);
DestroyWindow(label_handle);
DestroyWindow(total_progressbar_handle);
DestroyWindow(current_progressbar_handle);
}

void SetTotalMarquee(bool marquee) void SetTotalMarquee(bool marquee)
{ {
SetWindowLong(total_progressbar_handle, GWL_STYLE, SetWindowLong(total_progressbar_handle, GWL_STYLE,
@@ -199,49 +200,40 @@ void SetDescription(const std::string& text)


void MessageLoop() void MessageLoop()
{ {
request_stop.Clear();
running.Set();

if (!InitWindow()) if (!InitWindow())
{ {
running.Clear();
MessageBox(nullptr, L"Window init failed!", L"", MB_ICONERROR); MessageBox(nullptr, L"Window init failed!", L"", MB_ICONERROR);
// Destroying the parent (if exists) destroys all children windows
if (window_handle)
{
DestroyWindow(window_handle);
window_handle = nullptr;
}
return;
} }


SetTotalMarquee(true); SetTotalMarquee(true);
SetCurrentMarquee(true); SetCurrentMarquee(true);


while (!request_stop.IsSet()) MSG msg;
while (GetMessage(&msg, nullptr, 0, 0))
{ {
MSG msg; TranslateMessage(&msg);
while (PeekMessage(&msg, window_handle, 0, 0, PM_REMOVE)) DispatchMessage(&msg);
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
} }

running.Clear();

Destroy();
} }


void Init() void Init()
{ {
std::thread thread(MessageLoop); ui_thread = std::thread(MessageLoop);
thread.detach();
} }


void Stop() void Stop()
{ {
if (!running.IsSet()) if (window_handle)
return; PostMessage(window_handle, WM_CLOSE, 0, 0);


request_stop.Set(); ui_thread.join();

while (running.IsSet())
{
}
} }


void LaunchApplication(std::string path) void LaunchApplication(std::string path)
@@ -259,8 +251,11 @@ void Sleep(int sleep)
void WaitForPID(u32 pid) void WaitForPID(u32 pid)
{ {
HANDLE parent_handle = OpenProcess(SYNCHRONIZE, FALSE, static_cast<DWORD>(pid)); HANDLE parent_handle = OpenProcess(SYNCHRONIZE, FALSE, static_cast<DWORD>(pid));
WaitForSingleObject(parent_handle, INFINITE); if (parent_handle)
CloseHandle(parent_handle); {
WaitForSingleObject(parent_handle, INFINITE);
CloseHandle(parent_handle);
}
} }


void SetVisible(bool visible) void SetVisible(bool visible)

0 comments on commit 8f6b237

Please sign in to comment.
You can’t perform that action at this time.