adding windows auto-updater

This commit is contained in:
danteruiz 2019-09-24 18:45:42 -07:00
parent e6128003ec
commit f1fa2f8cd2
12 changed files with 188 additions and 58 deletions

View file

@ -11,7 +11,6 @@ set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON) set(CMAKE_AUTORCC ON)
#set(CMAKE_AUTOUIC ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_INCLUDE_CURRENT_DIR ON)
include("cmake/init.cmake") include("cmake/init.cmake")
@ -110,6 +109,8 @@ add_custom_command(
COMMAND "${_qt5Core_install_prefix}/bin/rcc" COMMAND "${_qt5Core_install_prefix}/bin/rcc"
ARGS ${RESOURCES_QRC} -binary -o ${RESOURCES_RCC}) ARGS ${RESOURCES_QRC} -binary -o ${RESOURCES_RCC})
QT5_ADD_RESOURCES(RES_SOURCES ${RESOURCES_QRC})
list(APPEND GENERATE_QRC_DEPENDS ${RESOURCES_RCC}) list(APPEND GENERATE_QRC_DEPENDS ${RESOURCES_RCC})
add_custom_target(resources ALL DEPENDS ${GENERATE_QRC_DEPENDS}) add_custom_target(resources ALL DEPENDS ${GENERATE_QRC_DEPENDS})
@ -134,14 +135,23 @@ set(src_files
src/Helper.cpp src/Helper.cpp
deps/miniz/miniz.h deps/miniz/miniz.h
deps/miniz/miniz.cpp deps/miniz/miniz.cpp
${RES_SOURCES}
) )
if (APPLE) if (APPLE)
set(src_files ${src_files} set(src_files ${src_files}
src/darwin/Helper.mm src/Helper_darwin.mm
src/darwin/NSTask+NSTaskExecveAdditions.h src/NSTask+NSTaskExecveAdditions.h
src/darwin/NSTask+NSTaskExecveAdditions.m src/NSTask+NSTaskExecveAdditions.m
)
endif()
if (WIN32)
set(src_files ${src_files}
src/Helper_windows.cpp
src/LauncherInstaller_windows.h
src/LauncherInstaller_windows.cpp
) )
endif() endif()
set(TARGET_NAME ${PROJECT_NAME}) set(TARGET_NAME ${PROJECT_NAME})
@ -149,7 +159,7 @@ set(TARGET_NAME ${PROJECT_NAME})
set_packaging_parameters() set_packaging_parameters()
if (WIN32) if (WIN32)
add_executable(${PROJECT_NAME} ${src_files}) add_executable(${PROJECT_NAME} ${src_files} build/resources.qrc)
elseif (APPLE) elseif (APPLE)
set_target_properties(${this_target} PROPERTIES set_target_properties(${this_target} PROPERTIES
MACOSX_BUNDLE_INFO_PLIST MacOSXBundleInfo.plist.in) MACOSX_BUNDLE_INFO_PLIST MacOSXBundleInfo.plist.in)
@ -220,6 +230,8 @@ else()
message("Use resource.rcc path: qrc:/") message("Use resource.rcc path: qrc:/")
endif() endif()
target_compile_definitions(${PROJECT_NAME} PRIVATE LAUNCHER_BUILD_VERSION="${BUILD_VERSION}")
if (APPLE) if (APPLE)
install( install(
TARGETS HQLauncher TARGETS HQLauncher

View file

@ -7,55 +7,6 @@
#include <QFile> #include <QFile>
#include <QProcess> #include <QProcess>
#if defined(Q_OS_WIN)
#include <Windows.h>
void launchClient(const QString& clientPath, const QString& homePath, const QString& defaultScriptsPath,
const QString& displayName, const QString& contentCachePath, QString loginResponseToken) {
// TODO Fix parameters
QString params = "--url \"" + homePath + "\""
+ " --setBookmark \"hqhome=" + homePath + "\""
+ " --defaultScriptsOverride \"" + defaultScriptsPath + "\""
+ " --displayName \"" + displayName + "\""
+ " --cache \"" + contentCachePath + "\"";
if (!loginResponseToken.isEmpty()) {
params += " --tokens \"" + loginResponseToken.replace("\"", "\\\"") + "\"";
}
STARTUPINFO si;
PROCESS_INFORMATION pi;
// set the size of the structures
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
// start the program up
BOOL success = CreateProcess(
clientPath.toUtf8().data(),
params.toUtf8().data(),
nullptr, // Process handle not inheritable
nullptr, // Thread handle not inheritable
FALSE, // Set handle inheritance to FALSE
CREATE_NEW_CONSOLE, // Opens file in a separate console
nullptr, // Use parent's environment block
nullptr, // Use parent's starting directory
&si, // Pointer to STARTUPINFO structure
&pi // Pointer to PROCESS_INFORMATION structure
);
// Close process and thread handles.
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
QCoreApplication::instance()->quit();
}
#endif
void swapLaunchers(const QString& oldLauncherPath, const QString& newLauncherPath) { void swapLaunchers(const QString& oldLauncherPath, const QString& newLauncherPath) {
if (!(QFileInfo::exists(oldLauncherPath) && QFileInfo::exists(newLauncherPath))) { if (!(QFileInfo::exists(oldLauncherPath) && QFileInfo::exists(newLauncherPath))) {

View file

@ -0,0 +1,70 @@
#include "Helper.h"
#include <QCoreApplication>
#include <Windows.h>
void launchClient(const QString& clientPath, const QString& homePath, const QString& defaultScriptsPath,
const QString& displayName, const QString& contentCachePath, QString loginResponseToken) {
// TODO Fix parameters
QString params = "--url \"" + homePath + "\""
+ " --setBookmark \"hqhome=" + homePath + "\""
+ " --defaultScriptsOverride \"" + defaultScriptsPath + "\""
+ " --displayName \"" + displayName + "\""
+ " --cache \"" + contentCachePath + "\"";
if (!loginResponseToken.isEmpty()) {
params += " --tokens \"" + loginResponseToken.replace("\"", "\\\"") + "\"";
}
STARTUPINFO si;
PROCESS_INFORMATION pi;
// set the size of the structures
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
// start the program up
BOOL success = CreateProcess(
clientPath.toUtf8().data(),
params.toUtf8().data(),
nullptr, // Process handle not inheritable
nullptr, // Thread handle not inheritable
FALSE, // Set handle inheritance to FALSE
CREATE_NEW_CONSOLE, // Opens file in a separate console
nullptr, // Use parent's environment block
nullptr, // Use parent's starting directory
&si, // Pointer to STARTUPINFO structure
&pi // Pointer to PROCESS_INFORMATION structure
);
// Close process and thread handles.
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
QCoreApplication::instance()->quit();
}
void launchAutoUpdater(const QString& autoUpdaterPath) {
QString params = "--restart --noUpdate";
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
BOOL success = CreateProcess(
autoUpdaterPath.toUtf8().data(),
params.toUtf8().data(),
nullptr, // Process handle not inheritable
nullptr, // Thread handle not inheritable
FALSE, // Set handle inheritance to FALSE
CREATE_NEW_CONSOLE, // Opens file in a separate console
nullptr, // Use parent's environment block
nullptr, // Use parent's starting directory
&si, // Pointer to STARTUPINFO structure
&pi // Pointer to PROCESS_INFORMATION structure
);
}

View file

@ -9,6 +9,7 @@
#include "PathUtils.h" #include "PathUtils.h"
Launcher::Launcher(int& argc, char**argv) : QGuiApplication(argc, argv) { Launcher::Launcher(int& argc, char**argv) : QGuiApplication(argc, argv) {
Q_INIT_RESOURCE(resources);
QString resourceBinaryLocation = QGuiApplication::applicationDirPath() + "/resources.rcc"; QString resourceBinaryLocation = QGuiApplication::applicationDirPath() + "/resources.rcc";
qDebug() << "resources.rcc path: " << resourceBinaryLocation; qDebug() << "resources.rcc path: " << resourceBinaryLocation;
QResource::registerResource(resourceBinaryLocation); QResource::registerResource(resourceBinaryLocation);

View file

@ -0,0 +1,43 @@
#include "LauncherInstaller_windows.h"
#include <Windows.h>
#include <QStandardPaths>
#include <QFileInfo>
#include <QFile>
#include <QDebug>
LauncherInstaller::LauncherInstaller(const QString& applicationFilePath) {
_launcherInstallDir = QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + "/HQ";
qDebug() << "Launcher install dir: " << _launcherInstallDir.absolutePath();
_launcherInstallDir.mkpath(_launcherInstallDir.absolutePath());
QFileInfo fileInfo(applicationFilePath);
_launcherRunningFilePath = fileInfo.absoluteFilePath();
_launcherRunningDirPath = fileInfo.absoluteDir().absolutePath();
qDebug() << "Launcher running file path: " << _launcherRunningFilePath;
qDebug() << "Launcher running dir path: " << _launcherRunningDirPath;
}
bool LauncherInstaller::runningOutsideOfInstallDir() {
return (QString::compare(_launcherInstallDir.absolutePath(), _launcherRunningDirPath) != 0);
}
void LauncherInstaller::install() {
if (runningOutsideOfInstallDir()) {
qDebug() << "Installing HQ Launcher....";
QString oldLauncherPath = _launcherInstallDir.absolutePath() + "/HQ Launcher.exe";
if (QFile::exists(oldLauncherPath)) {
bool didRemove = QFile::remove(oldLauncherPath);
qDebug() << "did remove file: " << didRemove;
}
bool success = QFile::copy(_launcherRunningFilePath, oldLauncherPath);
if (success) {
qDebug() << "successful";
} else {
qDebug() << "not successful";
}
}
}
void LauncherInstaller::uninstall() {}

View file

@ -0,0 +1,16 @@
#pragma once
#include <QDir>
class LauncherInstaller {
public:
LauncherInstaller(const QString& applicationFilePath);
~LauncherInstaller() = default;
void install();
void uninstall();
private:
bool runningOutsideOfInstallDir();
QDir _launcherInstallDir;
QString _launcherRunningFilePath;
QString _launcherRunningDirPath;
};

View file

@ -8,6 +8,7 @@
#include <Windows.h> #include <Windows.h>
#endif #endif
#include <array> #include <array>
#include <cstdlib>
#include <QProcess> #include <QProcess>
@ -69,7 +70,7 @@ bool LatestBuilds::getBuild(QString tag, Build* outBuild) {
} }
static const std::array<QString, LauncherState::UIState::UI_STATE_NUM> QML_FILE_FOR_UI_STATE = static const std::array<QString, LauncherState::UIState::UI_STATE_NUM> QML_FILE_FOR_UI_STATE =
{ { "qml/SplashScreen.qml", "qml/HFBase/CreateAccountBase.qml", "DisplayName.qml", { { "SplashScreen.qml", "qml/HFBase/CreateAccountBase.qml", "DisplayName.qml",
"qml/Download.qml", "qml/DownloadFinished.qml", "qml/HFBase/Error.qml" } }; "qml/Download.qml", "qml/DownloadFinished.qml", "qml/HFBase/Error.qml" } };
void LauncherState::ASSERT_STATE(LauncherState::ApplicationState state) { void LauncherState::ASSERT_STATE(LauncherState::ApplicationState state) {
@ -220,9 +221,17 @@ void LauncherState::receivedBuildsReply() {
} }
} }
if (shouldDownloadLauncher()) {
downloadLauncher();
}
getCurrentClientVersion(); getCurrentClientVersion();
} }
bool LauncherState::shouldDownloadLauncher() {
return _latestBuilds.launcherBuild.latestVersion != atoi(LAUNCHER_BUILD_VERSION);
}
void LauncherState::getCurrentClientVersion() { void LauncherState::getCurrentClientVersion() {
ASSERT_STATE(ApplicationState::RequestingBuilds); ASSERT_STATE(ApplicationState::RequestingBuilds);
@ -453,14 +462,17 @@ void LauncherState::downloadClient() {
void LauncherState::launcherDownloadComplete() { void LauncherState::launcherDownloadComplete() {
_launcherZipFile.close(); _launcherZipFile.close();
#ifdef Q_OS_MAC
installLauncher(); installLauncher();
#elif defined(Q_OS_WIN)
//launchAutoUpdater(_launcherZipFile.fileName());
#endif
} }
void LauncherState::clientDownloadComplete() { void LauncherState::clientDownloadComplete() {
ASSERT_STATE(ApplicationState::DownloadingClient); ASSERT_STATE(ApplicationState::DownloadingClient);
_clientZipFile.close(); _clientZipFile.close();
installClient(); installClient();
} }
@ -501,7 +513,11 @@ void LauncherState::downloadLauncher() {
auto request = new QNetworkRequest(QUrl(_latestBuilds.launcherBuild.installerZipURL)); auto request = new QNetworkRequest(QUrl(_latestBuilds.launcherBuild.installerZipURL));
auto reply = _networkAccessManager.get(*request); auto reply = _networkAccessManager.get(*request);
#ifdef Q_OS_MAC
_launcherZipFile.setFileName(_launcherDirectory.absoluteFilePath("launcher.zip")); _launcherZipFile.setFileName(_launcherDirectory.absoluteFilePath("launcher.zip"));
#elif defined(Q_OS_WIN)
_launcherZipFile.setFileName(_launcherDirectory.absoluteFilePath("launcher.exe"));
#endif
qDebug() << "opening " << _launcherZipFile.fileName(); qDebug() << "opening " << _launcherZipFile.fileName();
@ -525,8 +541,9 @@ void LauncherState::downloadLauncher() {
} }
void LauncherState::installLauncher() { void LauncherState::installLauncher() {
auto installDir = _launcherDirectory.absoluteFilePath("launcher_install"); _launcherDirectory.rmpath("launcher_install");
_launcherDirectory.mkpath("launcher_install"); _launcherDirectory.mkpath("launcher_install");
auto installDir = _launcherDirectory.absoluteFilePath("launcher_install");
qDebug() << "Uzipping " << _launcherZipFile.fileName() << " to " << installDir; qDebug() << "Uzipping " << _launcherZipFile.fileName() << " to " << installDir;

View file

@ -146,6 +146,8 @@ private:
QString getClientDirectory() const; QString getClientDirectory() const;
QString getClientExecutablePath() const; QString getClientExecutablePath() const;
bool shouldDownloadLauncher();
QNetworkAccessManager _networkAccessManager; QNetworkAccessManager _networkAccessManager;
LatestBuilds _latestBuilds; LatestBuilds _latestBuilds;
QDir _launcherDirectory; QDir _launcherDirectory;

View file

@ -7,6 +7,7 @@
#include "Helper.h" #include "Helper.h"
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
#include "LauncherInstaller_windows.h"
Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin); Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin);
#elif defined(Q_OS_MACOS) #elif defined(Q_OS_MACOS)
Q_IMPORT_PLUGIN(QCocoaIntegrationPlugin); Q_IMPORT_PLUGIN(QCocoaIntegrationPlugin);
@ -26,8 +27,18 @@ bool hasSuffix(const std::string path, const std::string suffix) {
return false; return false;
} }
bool containsOption(int argc, char* argv[], const std::string& option) {
for (int index = 0; index < argc; index++) {
if (option.compare(argv[index]) == 0) {
return true;
}
}
return false;
}
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
//std::cout << "Launcher version: " << LAUNCHER_BUILD_VERSION;
#ifdef Q_OS_MAC #ifdef Q_OS_MAC
// auto updater // auto updater
if (argc == 3) { if (argc == 3) {
@ -38,6 +49,13 @@ int main(int argc, char *argv[]) {
std::cout << "not swapping launcher \n"; std::cout << "not swapping launcher \n";
} }
} }
#elif defined(Q_OS_WIN)
// try-install
if (containsOption(argc, argv, "--restart")) {
LauncherInstaller launcherInstaller(argv[0]);
launcherInstaller.install();
}
#endif #endif
QString name { "High Fidelity" }; QString name { "High Fidelity" };
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);