mirror of
https://github.com/BTMuli/TeyvatGuide.git
synced 2026-05-15 04:27:39 +08:00
✨ 管理员模式下启动使用YAE导入
This commit is contained in:
@@ -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<u16> = to_wide_string(path);
|
||||
let cwd = std::path::Path::new(path).parent().unwrap().to_str().unwrap();
|
||||
let wide_cwd: Vec<u16> = to_wide_string(cwd);
|
||||
|
||||
pub fn spawn_process(path: &str, ticket: Option<String>) -> PROCESS_INFORMATION {
|
||||
let wide_path: Vec<u16> = to_wide_string(path); // 如果有 ticket,构造命令行
|
||||
let mut wide_cmd: Option<Vec<u16>> = 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<Vec<u16>> = 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::<STARTUPINFOW>() 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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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: Read>(r: &mut R, len: usize) -> io::Result<Vec<u8>> {
|
||||
|
||||
/// 调用 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<String>,
|
||||
) -> 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
|
||||
|
||||
@@ -133,8 +133,8 @@ async function handleYaeListen(event: Event<TGApp.Plugins.Yae.RsEvent>): 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<TGApp.Plugins.Yae.RsEvent>): Promise
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function loadYaeAchi(uid: string, data: TGApp.Plugins.Yae.AchiListRes): Promise<void> {
|
||||
console.warn("成就数据", data);
|
||||
await showLoading.start("正在导入成就数据", `UID:${uid},数量:${data.length}`);
|
||||
await TGLogger.Info(`[App][loadYaeAchi] 开始处理 ${uid} 的 ${data.length} 条成就数据`);
|
||||
try {
|
||||
|
||||
@@ -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<void> {
|
||||
showSnackbar.warn("未检测到原神本体应用!");
|
||||
return;
|
||||
}
|
||||
let isAdmin = false;
|
||||
try {
|
||||
isAdmin = await invoke<boolean>("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<void> {
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user