From cd946a60fb12c8a536dd903dca5583bb37240d16 Mon Sep 17 00:00:00 2001 From: Minoricew <154642983+Minoricew@users.noreply.github.com> Date: Tue, 18 Nov 2025 19:37:52 +0800 Subject: [PATCH] =?UTF-8?q?[=F0=9F=9B=A0=EF=B8=8F=20Fix]=20Add=20vcredist?= =?UTF-8?q?=20inst=20check=20&=20Improve=20Aikari=20lifecycle=20mgmt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. [+] 添加了对于 VC Redist 是否安装的状态检查 & 引导 2. [*] 略微调整和改进了 Aikari 的生命周期管理, 避免彻底卡死等情况, 添加更多的错误说明 --- package.json | 2 +- .../init/main/ipcModules/aikariIpcHandler.js | 20 +++- src/aura/ui/composables/rawCmdExec/app.js | 34 +++++++ src/aura/ui/js/aikariConnectionManager.js | 54 +++++++---- .../behaviourCtrl/aikariStatus.js | 94 +++++++++++++++++-- .../freezeOverridePreview.html | 2 +- src/core/preload.js | 2 +- 7 files changed, 178 insertions(+), 30 deletions(-) create mode 100644 src/aura/ui/composables/rawCmdExec/app.js diff --git a/package.json b/package.json index c30d1b8..c21e82b 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "HugoAura", - "version": "0.2.0-rc1", + "version": "0.2.0-rc1-p1", "description": "Aura for SeewoHugo", "main": "app.asar/main.js", "dependencies": {}, diff --git a/src/aura/init/main/ipcModules/aikariIpcHandler.js b/src/aura/init/main/ipcModules/aikariIpcHandler.js index 01ffa29..9ff0c1d 100644 --- a/src/aura/init/main/ipcModules/aikariIpcHandler.js +++ b/src/aura/init/main/ipcModules/aikariIpcHandler.js @@ -696,13 +696,31 @@ const applyAikariIpcHandler = (ipcMain) => { } ); + ipcMain.handle( + `${methodBase}.forceReloadKeepAliveWin`, + /** + * + * @param {import("electron").IpcMainInvokeEvent} _event + * @param {any} arg + */ + (_event, arg) => { + ipcMain.send( + "auraWsKeepAlive", + `${methodBase}.post.onForceReloadRequested`, + arg + ); + + return { success: true }; + } + ); + ipcMain.handle( `${methodBase}.post.updateRetryStatus`, /** * * @param {import("electron").IpcMainInvokeEvent} _event - * @param {{ success: boolean }} arg + * @param {{ success: boolean; message: string }} arg */ (_event, arg) => { ipcMain.send("assistant", `${methodBase}.post.updateRetryStatus`, arg); diff --git a/src/aura/ui/composables/rawCmdExec/app.js b/src/aura/ui/composables/rawCmdExec/app.js new file mode 100644 index 0000000..744dcc8 --- /dev/null +++ b/src/aura/ui/composables/rawCmdExec/app.js @@ -0,0 +1,34 @@ +const childProc = require("child_process"); + +const appRawCmds = { + checkVcRedistInst: async () => { + let deviceArch = process.env.PROCESSOR_ARCHITEW6432 + ? process.env.PROCESSOR_ARCHITEW6432 + : process.env.PROCESSOR_ARCHITECTURE; + // @ts-expect-error + deviceArch = deviceArch.toLowerCase(); + if (deviceArch === "amd64") { + deviceArch = "x64"; + } else if (deviceArch === "arm64") { + // do nothing + } + const waitForCmd = new Promise((resolve) => { + childProc.exec( + `reg query "HKLM\\SOFTWARE\\Microsoft\\VisualStudio\\14.0\\VC\\Runtimes\\${deviceArch}" /v Installed`, + (error, stdout, stderr) => { + if (error) { + console.warn( + `[HugoAura / UI / Composables / Raw CMD / APP] Detected VS Redist not installed: ${stderr}` + ); + resolve({ installed: false, arch: deviceArch }); + } else { + resolve({ installed: true, arch: deviceArch }); + } + } + ); + }); + return waitForCmd; + }, +}; + +module.exports = appRawCmds; diff --git a/src/aura/ui/js/aikariConnectionManager.js b/src/aura/ui/js/aikariConnectionManager.js index 125c5ac..8826e19 100644 --- a/src/aura/ui/js/aikariConnectionManager.js +++ b/src/aura/ui/js/aikariConnectionManager.js @@ -38,9 +38,9 @@ let isErrorOccurred = false; /** @type {number} */ - let plsPort = 22077; + let aikariPort = 22077; /** @type {"wss" | "ws"} */ - let plsProtocol = "wss"; + let aikariProtocol = "wss"; /** @type {boolean} */ let isRetrying = false; @@ -49,9 +49,13 @@ let curSendListener = null; let curSendGetListener = null; - const sendRetryStatusToMain = (/** @type {Boolean} */ status) => { + const sendRetryStatusToMain = ( + /** @type {Boolean} */ status, + /** @type {string?} */ message = null + ) => { global.ipcRenderer.invoke(`${IPC_METHOD_BASE}.post.updateRetryStatus`, { success: status, + message: message, }); }; @@ -86,7 +90,7 @@ // @ts-expect-error global.__HUGO_AURA__.aikariStats.authToken = authTokenRet.data; } else { - sendRetryStatusToMain(false); + sendRetryStatusToMain(false, "E_AUTH_TOKEN_GET_FAILED"); return; } const portRet = await registryManager.readRegKey( @@ -96,7 +100,7 @@ ); if (portRet.success) { try { - plsPort = Number(portRet.data); + aikariPort = Number(portRet.data); } catch { console.warn( `[HugoAura / UI / Aikari Conn Manager] Invalid Aikari port: ${portRet.data}` @@ -104,7 +108,10 @@ } } // TODO: wsHost - createAikariConnection(updatedAikariStats.authToken, connectionResultCallback); + createAikariConnection( + updatedAikariStats.authToken, + connectionResultCallback + ); }; /** @@ -116,18 +123,20 @@ const createAikariConnection = (authToken, callback) => { if (failedCounter >= 3) { console.error( - `[HugoAura / UI / Aikari Conn Manager / ERROR] Failed connecting to PLS WebSocket server, please check the status of PLS process.` + `[HugoAura / UI / Aikari Conn Manager / ERROR] Failed connecting to Aikari WebSocket server, please check the status of Aikari process.` ); - sendRetryStatusToMain(false); + sendRetryStatusToMain(false, "E_WS_CONN_FAILED_AFT_MULTIPLE_TRIES"); return; } /** @type {WebSocket} */ const aikariWs = new WebSocket( - `${plsProtocol}://aikari.hugoaura.local:${plsPort}/?auth=${authToken}` + `${aikariProtocol}://aikari.hugoaura.local:${aikariPort}/?auth=${authToken}` ); aikariWs.onopen = () => { + failedCounter = 0; + isErrorOccurred = false; callback(true, aikariWs); }; @@ -142,7 +151,7 @@ if (global.__HUGO_AURA__.aikariStats) { if (global.__HUGO_AURA__.aikariStats.status === "notReady") { if (isRetrying) { - sendRetryStatusToMain(false); + sendRetryStatusToMain(false, "E_IS_LOADING"); return; } console.warn( @@ -153,7 +162,7 @@ isRetrying = false; startConnAikariProc(global.__HUGO_AURA__.aikariStats); }, 10000); - sendRetryStatusToMain(false); + sendRetryStatusToMain(false, "E_START_WAIT_FOR_LOADING"); return; } @@ -234,7 +243,7 @@ global.__HUGO_AURA__.aikariStats ); - sendRetryStatusToMain(true); + sendRetryStatusToMain(true, "SUCCESS"); }; /** @@ -275,21 +284,21 @@ if (!global.__HUGO_AURA__.aikariStats) return; if (isRetrying) { - sendRetryStatusToMain(false); + sendRetryStatusToMain(false, "E_RETRY_PENDING"); return; } failedCounter = 0; isErrorOccurred = false; - const curPlsStats = await global.ipcRenderer.invoke( + const curAikariStats = await global.ipcRenderer.invoke( `${IPC_METHOD_BASE}.getAikariStatus` ); let updatedAikariStats = {}; if ( - (curPlsStats === null || !curPlsStats.success) && - curPlsStats.status !== "downloading" && - curPlsStats.status !== "installing" + (curAikariStats === null || !curAikariStats.success) && + curAikariStats.status !== "downloading" && + curAikariStats.status !== "installing" ) { updatedAikariStats = { installed: false, @@ -301,7 +310,7 @@ authToken: "", }; } else { - updatedAikariStats = curPlsStats.data; + updatedAikariStats = curAikariStats.data; } const isAikariBinExists = ( @@ -326,7 +335,7 @@ if (updatedAikariStats.installed || updatedAikariStats.detached) { await startConnAikariProc(updatedAikariStats); } else { - sendRetryStatusToMain(false); + sendRetryStatusToMain(false, "E_NOT_INSTALLED"); } /* @@ -355,6 +364,13 @@ } ); + global.ipcRenderer.on( + `${IPC_METHOD_BASE}.post.onForceReloadRequested`, + (_evt, _arg) => { + window.location.reload(); + } + ); + global.ipcRenderer.on( `${IPC_METHOD_BASE}.post.aikariStopped`, (_evt, _arg) => { diff --git a/src/aura/ui/pages/configSubPages/behaviourCtrl/aikariStatus.js b/src/aura/ui/pages/configSubPages/behaviourCtrl/aikariStatus.js index 30d99c5..d390b22 100644 --- a/src/aura/ui/pages/configSubPages/behaviourCtrl/aikariStatus.js +++ b/src/aura/ui/pages/configSubPages/behaviourCtrl/aikariStatus.js @@ -8,6 +8,8 @@ if (!global.__HUGO_AURA_UI_REACTIVES__.subConfig) const REQUIRE_BASE = "../../aura/ui/pages/configSubPages/behaviourCtrl"; const IPC_METHOD_BASE = "$aura.aikari"; + const appRawCmds = require(`${REQUIRE_BASE}/../../../composables/rawCmdExec/app`); + const lifecycleStatus = { installed: false, detached: false, @@ -21,6 +23,30 @@ if (!global.__HUGO_AURA_UI_REACTIVES__.subConfig) }; global.__HUGO_AURA_UI_FUNCTIONS__.subConfig.aikariStatus = { + openLink: async (link) => { + const childProc = require("child_process"); + childProc.spawn("cmd.exe", [`/k start ${link}`]); + }, + + getRetryStatusDescByErrId: (errIdString) => { + switch (errIdString) { + case "E_AUTH_TOKEN_GET_FAILED": + return `

Aikari 注册表访问失败, 这是一个极为罕见的问题

+

请检查 HKEY_USERS\\.DEFAULT 是否存在, 并反馈至 GitHub Issues

`; + case "E_WS_CONN_FAILED_AFT_MULTIPLE_TRIES": + return `

在多次尝试连接后仍然失败, 请检查服务是否已启动

`; + case "E_IS_LOADING": + case "E_START_WAIT_FOR_LOADING": + return `

Aikari 正在加载中, 请稍作等待

`; // 此提示理论上在当前版本不会出现 + case "E_RETRY_PENDING": + return `

正在尝试重连中, 请勿重复操作

`; + case "E_NOT_INSTALLED": + return `

Aikari 未安装, 请安装后继续

`; + default: + return null; + } + }, + updateToast: async ( variant, title, @@ -583,22 +609,41 @@ if (!global.__HUGO_AURA_UI_REACTIVES__.subConfig) if (result.success && result.status === "Retrying") { updateOperationBtnStatus("Refresh", true, "正在重连"); + let isRefreshCompleted = false; + ipcRenderer.once( `${IPC_METHOD_BASE}.post.updateRetryStatus`, async (_evt, arg) => { await global.__HUGO_AURA_GLOBAL__.utils.sleep(50); updateOperationBtnStatus("Refresh", false, "刷新状态"); + isRefreshCompleted = true; global.__HUGO_AURA_UI_FUNCTIONS__.subConfig.aikariStatus.updateToast( arg.success ? "success" : "error", arg.success ? "更新成功" : "连接失败", - null, + global.__HUGO_AURA_UI_FUNCTIONS__.subConfig.aikariStatus.getRetryStatusDescByErrId( + arg.message + ), true, true, - 3000 + 5000 ); global.__HUGO_AURA_UI_FUNCTIONS__.subConfig.aikariStatus.updateStatusContent(); } ); + + setTimeout(() => { + if (!isRefreshCompleted) { + ipcRenderer.invoke(`${IPC_METHOD_BASE}.forceReloadKeepAliveWin`); + global.__HUGO_AURA_UI_FUNCTIONS__.subConfig.aikariStatus.updateToast( + "error", + "连接控制器无响应, 强制重载中...", + null, + true, + true, + 4000 + ); + } + }, 8000); } else if (result.success && result.status === "Already") { updateOperationBtnStatus("Refresh", false, "刷新状态"); global.__HUGO_AURA_UI_FUNCTIONS__.subConfig.aikariStatus.updateToast( @@ -690,8 +735,8 @@ if (!global.__HUGO_AURA_UI_REACTIVES__.subConfig) "准备开始下载...", null, true, - true, - 2000 + false, + undefined ); GLOBAL_FUNCTIONS.updateOperationBtnStatus("Install", true); } else { @@ -700,8 +745,8 @@ if (!global.__HUGO_AURA_UI_REACTIVES__.subConfig) "正在恢复下载状态", null, true, - true, - 2000 + false, + undefined ); } @@ -711,7 +756,14 @@ if (!global.__HUGO_AURA_UI_REACTIVES__.subConfig) const callbackFn = (_evt, info) => { switch (info.status) { case "failed": - if (info.id !== "INSTALL_STAGE") { + if (info.id === "PRECHECK_STAGE") { + GLOBAL_FUNCTIONS.updatePBarStatus( + 100, + info.message, + "danger", + false + ); + } else if (info.id !== "INSTALL_STAGE") { GLOBAL_FUNCTIONS.updateToast( "error", "下载失败", @@ -879,6 +931,34 @@ if (!global.__HUGO_AURA_UI_REACTIVES__.subConfig) } }; + const isVcRedistInstalledPrecheck = await appRawCmds.checkVcRedistInst(); + if (!isVcRedistInstalledPrecheck.installed) { + callbackFn(null, { + id: "PRECHECK_STAGE", + progress: 100, + status: "failed", + dlUrl: null, + savePath: null, + message: "Visual C++ Redist 2015~2022 未安装", + }); + + setTimeout(() => { + GLOBAL_FUNCTIONS.updateToast( + "error", + "发生错误", + `

Aikari 需要 Visual C++ Redist 2015~2022 运行时以启动

+

请访问 + 此链接 + 以下载并安装运行时

`, + true, + false, + undefined + ); + }, 500); + + return; + } + ipcRenderer.on(CUR_CHANNEL, callbackFn); ipcRenderer.invoke(`${IPC_METHOD_BASE}.downloadAndInstallAikari`, { diff --git a/src/aura/ui/pages/configSubPages/behaviourCtrl/settings/previews/freezeOverridePreview/freezeOverridePreview.html b/src/aura/ui/pages/configSubPages/behaviourCtrl/settings/previews/freezeOverridePreview/freezeOverridePreview.html index b41db12..0977e99 100755 --- a/src/aura/ui/pages/configSubPages/behaviourCtrl/settings/previews/freezeOverridePreview/freezeOverridePreview.html +++ b/src/aura/ui/pages/configSubPages/behaviourCtrl/settings/previews/freezeOverridePreview/freezeOverridePreview.html @@ -13,7 +13,7 @@ -

请稍候...

+

无数据可用, 检查 Aikari 连接

diff --git a/src/core/preload.js b/src/core/preload.js index a6a420c..e1da9db 100755 --- a/src/core/preload.js +++ b/src/core/preload.js @@ -1,6 +1,6 @@ // @ts-check -const __AURA_VERSION__ = "0.2.0-rc1"; +const __AURA_VERSION__ = "0.2.0-rc1-p1"; (() => { if (require.main) return; // 如果只是导入 Aura Version, 不运行闭包逻辑