144 lines
5.6 KiB
C++
144 lines
5.6 KiB
C++
#include <windows.h>
|
|
#include <QApplication>
|
|
#include <QDebug>
|
|
#include <QMessageBox>
|
|
#include <QProcess>
|
|
#include <QProgressDialog>
|
|
#include <QTextCodec>
|
|
#include "UpdateLogic.h"
|
|
#include "../Common/ConfigHelper.h"
|
|
#include "../Common/PolicyHelper.h"
|
|
#include "../Common/LocalStateHelper.h"
|
|
|
|
int main(int argc, char* argv[])
|
|
{
|
|
SetConsoleOutputCP(65001);
|
|
QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"));
|
|
QApplication app(argc, argv);
|
|
QApplication::setApplicationName("Marsco Launcher");
|
|
|
|
QProgressDialog progress("正在检查软件更新...", QString(), 0, 0);
|
|
progress.setWindowTitle("Marsco 软件启动器");
|
|
progress.setCancelButton(nullptr);
|
|
progress.setWindowModality(Qt::ApplicationModal);
|
|
progress.setMinimumDuration(0);
|
|
progress.setAutoClose(false);
|
|
progress.show();
|
|
QApplication::processEvents();
|
|
|
|
UpdateLogic logic;
|
|
logic.checkUpdate();
|
|
|
|
const bool needUpdate = logic.getNeedUpdate();
|
|
const bool networkOk = logic.isNetworkOk();
|
|
const QString latestVer = logic.getLatestVersion();
|
|
const QJsonObject response = logic.getCheckResult();
|
|
const int targetVersionId = response.value("version_id").toInt();
|
|
const QString appId = logic.getAppId();
|
|
const QString channel = logic.getChannel();
|
|
|
|
ConfigHelper& config = ConfigHelper::instance();
|
|
const QString launchToken = config.getValue("App", "launch_token");
|
|
const QString currentVersion = config.getValue("App", "current_version");
|
|
const QString appDir = QApplication::applicationDirPath();
|
|
const QString mainAppPath = appDir + "/MainApp.exe";
|
|
const QString updaterPath = appDir + "/Updater.exe";
|
|
const QStringList mainArgs{QString("--launcher-token=%1").arg(launchToken)};
|
|
|
|
progress.setLabelText("正在验证本地运行策略...");
|
|
QApplication::processEvents();
|
|
|
|
PolicyHelper policy(appDir);
|
|
if (!policy.loadPolicy("config/version_policy.dat") || !policy.isValid())
|
|
{
|
|
progress.close();
|
|
QMessageBox::critical(nullptr, "无法启动", QString("本地版本策略无效:%1").arg(policy.errorString()));
|
|
return -1;
|
|
}
|
|
if (policy.isExpired())
|
|
{
|
|
progress.close();
|
|
QMessageBox::critical(nullptr, "无法启动", "本地版本策略已过期,请连接网络或联系管理员。");
|
|
return -1;
|
|
}
|
|
if ((!policy.allowRun() || !policy.isVersionAllowed(currentVersion)) && !(networkOk && needUpdate))
|
|
{
|
|
progress.close();
|
|
QMessageBox::critical(nullptr, "当前版本不可运行",
|
|
policy.message().isEmpty() ? QString("当前版本 %1 已被管理员停用。").arg(currentVersion)
|
|
: policy.message());
|
|
return -1;
|
|
}
|
|
|
|
LocalStateHelper state(appDir);
|
|
if (!state.loadState())
|
|
{
|
|
progress.close();
|
|
QMessageBox::critical(nullptr, "无法启动", QString("无法读取本地状态:%1").arg(state.errorString()));
|
|
return -1;
|
|
}
|
|
if (state.isPolicySeqRolledBack(policy.policySeq()))
|
|
{
|
|
progress.close();
|
|
QMessageBox::critical(nullptr, "安全检查失败", "检测到版本策略序列回退,已阻止启动。");
|
|
return -1;
|
|
}
|
|
if (state.isSystemTimeRewound())
|
|
{
|
|
progress.close();
|
|
QMessageBox::critical(nullptr, "安全检查失败", "检测到系统时间可能被回拨,已阻止启动。");
|
|
return -1;
|
|
}
|
|
|
|
if (networkOk && needUpdate)
|
|
{
|
|
progress.close();
|
|
const bool rollbackOperation = response.value("action").toString() == "rollback_allowed";
|
|
const QString dialogTitle = rollbackOperation ? "版本回退"
|
|
: (policy.forceUpdate() ? "必须更新" : "发现新版本");
|
|
const QString prompt = policy.message().isEmpty()
|
|
? QString(rollbackOperation ? "管理员提供了版本 %1 作为回退目标,是否现在降级?"
|
|
: "发现新版本 %1,是否现在更新?").arg(latestVer)
|
|
: policy.message() + QString("\n目标版本:%1").arg(latestVer);
|
|
bool accepted = true;
|
|
if (policy.forceUpdate()) {
|
|
QMessageBox::information(nullptr, dialogTitle, prompt);
|
|
} else {
|
|
accepted = QMessageBox::question(nullptr, dialogTitle, prompt,
|
|
QMessageBox::Yes | QMessageBox::No, QMessageBox::No) == QMessageBox::Yes;
|
|
}
|
|
if (!accepted) {
|
|
if (!QProcess::startDetached(mainAppPath, mainArgs)) {
|
|
QMessageBox::critical(nullptr, "启动失败", QString("无法启动主程序:%1").arg(mainAppPath));
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
const QStringList updaterArgs{appId, channel, latestVer, QString::number(targetVersionId)};
|
|
if (!QProcess::startDetached(updaterPath, updaterArgs))
|
|
{
|
|
QMessageBox::critical(nullptr, "更新器启动失败", QString("无法启动更新器:%1").arg(updaterPath));
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
if (!networkOk && !policy.isOfflineAllowed())
|
|
{
|
|
progress.close();
|
|
QMessageBox::critical(nullptr, "网络不可用", "无法连接更新服务器,且当前策略不允许离线启动。");
|
|
return -1;
|
|
}
|
|
|
|
progress.setLabelText(networkOk ? "当前已是最新版本,正在启动..." : "当前处于离线模式,正在启动...");
|
|
QApplication::processEvents();
|
|
if (!QProcess::startDetached(mainAppPath, mainArgs))
|
|
{
|
|
progress.close();
|
|
QMessageBox::critical(nullptr, "启动失败", QString("无法启动主程序:%1").arg(mainAppPath));
|
|
return -1;
|
|
}
|
|
progress.close();
|
|
return 0;
|
|
}
|