mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-25 15:19:42 -06:00
Merge pull request #8217 from CookiePLMonster/windows-updater-improvements
Updates to auto-updater on Windows
This commit is contained in:
@ -95,6 +95,11 @@ void Updater::OnUpdateAvailable(const NewVersionInformation& info)
|
|||||||
AutoUpdateChecker::RestartMode::RESTART_AFTER_UPDATE);
|
AutoUpdateChecker::RestartMode::RESTART_AFTER_UPDATE);
|
||||||
|
|
||||||
if (!later)
|
if (!later)
|
||||||
|
{
|
||||||
|
RunOnObject(m_parent, [this] {
|
||||||
m_parent->close();
|
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;
|
MSG msg;
|
||||||
while (PeekMessage(&msg, window_handle, 0, 0, PM_REMOVE))
|
while (GetMessage(&msg, nullptr, 0, 0))
|
||||||
{
|
{
|
||||||
TranslateMessage(&msg);
|
TranslateMessage(&msg);
|
||||||
DispatchMessage(&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,9 +251,12 @@ 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));
|
||||||
|
if (parent_handle)
|
||||||
|
{
|
||||||
WaitForSingleObject(parent_handle, INFINITE);
|
WaitForSingleObject(parent_handle, INFINITE);
|
||||||
CloseHandle(parent_handle);
|
CloseHandle(parent_handle);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SetVisible(bool visible)
|
void SetVisible(bool visible)
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user