From 06ff32d47db8e4e02457608883e5d57c60d8085c Mon Sep 17 00:00:00 2001 From: BTMuli Date: Mon, 22 Dec 2025 15:56:53 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20=E7=AE=A1=E7=90=86=E5=91=98?= =?UTF-8?q?=E6=A8=A1=E5=BC=8F=E4=B8=8B=E5=90=AF=E5=8A=A8=E4=BD=BF=E7=94=A8?= =?UTF-8?q?YAE=E5=AF=BC=E5=85=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src-tauri/src/yae/inject.rs | 27 ++++++++++++--------- src-tauri/src/yae/mod.rs | 11 ++++++--- src/App.vue | 5 ++-- src/components/app/t-sidebar.vue | 41 +++++++++++++++++++++++++------- 4 files changed, 59 insertions(+), 25 deletions(-) diff --git a/src-tauri/src/yae/inject.rs b/src-tauri/src/yae/inject.rs index e2da7748..e75df41e 100644 --- a/src-tauri/src/yae/inject.rs +++ b/src-tauri/src/yae/inject.rs @@ -1,5 +1,5 @@ //! DLL 注入相关功能 -//! @since Beta v0.7.8 +//! @since Beta v0.9.1 #![cfg(target_os = "windows")] use std::ffi::OsStr; @@ -53,33 +53,38 @@ pub fn create_named_pipe(pipe_name: &str) -> HANDLE { } /// 启动目标进程,附加cwd -pub fn spawn_process(path: &str) -> PROCESS_INFORMATION { - let wide_path: Vec = to_wide_string(path); - let cwd = std::path::Path::new(path).parent().unwrap().to_str().unwrap(); - let wide_cwd: Vec = to_wide_string(cwd); - +pub fn spawn_process(path: &str, ticket: Option) -> PROCESS_INFORMATION { + let wide_path: Vec = to_wide_string(path); // 如果有 ticket,构造命令行 + let mut wide_cmd: Option> = None; + if let Some(ref t) = ticket { + let cmdline = format!("{} login_auth_ticket={}", path, t); + wide_cmd = Some(to_wide_string(&cmdline)); + } // 如果没有 ticket,使用 cwd + let wide_cwd: Option> = if ticket.is_none() { + let cwd = std::path::Path::new(path).parent().unwrap().to_str().unwrap(); + Some(to_wide_string(cwd)) + } else { + None + }; unsafe { let mut si: STARTUPINFOW = std::mem::zeroed(); si.cb = std::mem::size_of::() as u32; let mut pi: PROCESS_INFORMATION = std::mem::zeroed(); - let success = CreateProcessW( wide_path.as_ptr(), - ptr::null_mut(), + wide_cmd.as_mut().map(|v| v.as_mut_ptr()).unwrap_or(ptr::null_mut()), // 有 ticket 时传命令行 ptr::null_mut(), ptr::null_mut(), 0, 0, ptr::null_mut(), - wide_cwd.as_ptr(), + wide_cwd.as_ref().map(|v| v.as_ptr()).unwrap_or(ptr::null()), // 无 ticket 时传 cwd &mut si, &mut pi, ); - if success == 0 { panic!("CreateProcessW failed"); } - pi } } diff --git a/src-tauri/src/yae/mod.rs b/src-tauri/src/yae/mod.rs index f98a552d..46edbc92 100644 --- a/src-tauri/src/yae/mod.rs +++ b/src-tauri/src/yae/mod.rs @@ -1,5 +1,5 @@ //! Yae 相关处理 -//! @since Beta v0.8.9 +//! @since Beta v0.9.1 #![cfg(target_os = "windows")] pub mod inject; @@ -67,7 +67,12 @@ fn read_exact_vec(r: &mut R, len: usize) -> io::Result> { /// 调用 dll #[tauri::command] -pub fn call_yae_dll(app_handle: AppHandle, game_path: String, uid: String) -> Result<(), String> { +pub fn call_yae_dll( + app_handle: AppHandle, + game_path: String, + uid: String, + ticket: Option, +) -> Result<(), String> { let dll_path = app_handle.path().resource_dir().unwrap().join("resources/YaeAchievementLib.dll"); dbg!(&dll_path); // 0. 创建 YaeAchievementPipe 的 命名管道,获取句柄 @@ -75,7 +80,7 @@ pub fn call_yae_dll(app_handle: AppHandle, game_path: String, uid: String) -> Re let _pipe_handle = create_named_pipe("YaeAchievementPipe"); // 1. 启动游戏进程 - let pi = spawn_process(&game_path); + let pi = spawn_process(&game_path, ticket); dbg!("游戏进程启动完成"); // 2. 注入 DLL diff --git a/src/App.vue b/src/App.vue index b84548c9..c589ce6f 100644 --- a/src/App.vue +++ b/src/App.vue @@ -133,8 +133,8 @@ async function handleYaeListen(event: Event): Promise yaeFlag = []; showSnackbar.success(`导入Yae数据完成,即将刷新页面`); await showLoading.end(); - await new Promise((resolve) => setTimeout(resolve, 1000)); - window.location.reload(); + // await new Promise((resolve) => setTimeout(resolve, 1000)); + // window.location.reload(); } } @@ -145,6 +145,7 @@ async function handleYaeListen(event: Event): Promise * @returns {Promise} */ async function loadYaeAchi(uid: string, data: TGApp.Plugins.Yae.AchiListRes): Promise { + console.warn("成就数据", data); await showLoading.start("正在导入成就数据", `UID:${uid},数量:${data.length}`); await TGLogger.Info(`[App][loadYaeAchi] 开始处理 ${uid} 的 ${data.length} 条成就数据`); try { diff --git a/src/components/app/t-sidebar.vue b/src/components/app/t-sidebar.vue index e5f4bdc3..8f892a86 100644 --- a/src/components/app/t-sidebar.vue +++ b/src/components/app/t-sidebar.vue @@ -292,6 +292,7 @@ import TSUserAccount from "@Sqlm/userAccount.js"; import useAppStore from "@store/app.js"; import useUserStore from "@store/user.js"; import { event, path, webviewWindow } from "@tauri-apps/api"; +import { invoke } from "@tauri-apps/api/core"; import type { Event, UnlistenFn } from "@tauri-apps/api/event"; import { exists } from "@tauri-apps/plugin-fs"; import { Command } from "@tauri-apps/plugin-shell"; @@ -668,6 +669,14 @@ async function tryLaunchGame(): Promise { showSnackbar.warn("未检测到原神本体应用!"); return; } + let isAdmin = false; + try { + isAdmin = await invoke("is_in_admin"); + } catch (err) { + showSnackbar.error(`检测管理员权限失败:${err}`); + await TGLogger.Error(`[pageAchi][toYae]检测管理员权限失败:${err}`); + return; + } const resp = await passportReq.authTicket(account.value, cookie.value); if (typeof resp !== "string") { showSnackbar.error(`[${resp.retcode}] ${resp.message}`); @@ -677,15 +686,29 @@ async function tryLaunchGame(): Promise { await TGLogger.Error(`[sidebar][tryLaunchGame] resp: ${JSON.stringify(resp)}`); return; } - showSnackbar.success(`成功获取ticket:${resp},正在启动应用...`); - const cmd = Command.create("exec-sh", [`&"${gamePath}" login_auth_ticket=${resp}`], { - cwd: gameDir.value, - encoding: "utf-8", - }); - const result = await cmd.execute(); - if (result.stderr) { - await TGLogger.Error(`[sidebar][tryLaunchGame] 启动游戏本体失败!`); - showSnackbar.error(`启动游戏本体失败,代码:${result.code}`); + if (!isAdmin) { + showSnackbar.success(`成功获取ticket:${resp},正在启动应用...`); + const cmd = Command.create("exec-sh", [`&"${gamePath}" login_auth_ticket=${resp}`], { + cwd: gameDir.value, + encoding: "utf-8", + }); + const result = await cmd.execute(); + if (result.stderr) { + await TGLogger.Error(`[sidebar][tryLaunchGame] 启动游戏本体失败!`); + showSnackbar.error(`启动游戏本体失败,代码:${result.code}`); + } + } else { + try { + await invoke("call_yae_dll", { + gamePath: gamePath, + uid: account.value.gameUid, + ticket: resp, + }); + } catch (err) { + showSnackbar.error(`调用Yae DLL失败: ${err}`); + await TGLogger.Error(`[pageAchi][toYae]调用Yae DLL失败: ${err}`); + return; + } } }