mirror of
https://github.com/HolographicHat/Yae.git
synced 2025-12-16 03:18:12 +08:00
update
This commit is contained in:
@@ -1,8 +1,18 @@
|
||||
namespace YaeAchievement;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace YaeAchievement;
|
||||
|
||||
[SuppressMessage("Usage", "CA2211:非常量字段应当不可见")]
|
||||
[SuppressMessage("ReSharper", "ConvertToConstant.Global")]
|
||||
[SuppressMessage("ReSharper", "FieldCanBeMadeReadOnly.Global")]
|
||||
public static class GlobalVars {
|
||||
|
||||
public static bool Verbose = false;
|
||||
public const string LibName = "YaeAchievementLib.dll";
|
||||
public const string PipeName = "YaeAchievementPipe";
|
||||
public static bool UnexpectedExit = true;
|
||||
public static string GamePath = "";
|
||||
|
||||
public const string LibName = "YaeLib.dll";
|
||||
public const string PipeName = "YaeAchievementPipe";
|
||||
public const string ConfigFileName = "YaeAchievement.runtimeconfig.json";
|
||||
|
||||
}
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.IO.Pipes;
|
||||
using YaeAchievement;
|
||||
using YaeAchievement.Win32;
|
||||
using YaeAchievement;
|
||||
using static YaeAchievement.Utils;
|
||||
|
||||
|
||||
Utils.StartAndWaitResult(@"D:\Genshin Impact Dev\2.8\YuanShen.exe", str => {
|
||||
InstallExitHook();
|
||||
InstallExceptionHook();
|
||||
CheckGenshinIsRunning();
|
||||
LoadConfig();
|
||||
return;
|
||||
StartAndWaitResult(@"D:\Genshin Impact Dev\2.8\YuanShen.exe", str => {
|
||||
GlobalVars.UnexpectedExit = false;
|
||||
//AchievementAllDataNotify.Parser.ParseFrom(Convert.FromBase64String(str)).List;
|
||||
//var notify = Serializer.Deserialize<AchievementAllDataNotify>(stream)!;
|
||||
|
||||
72
src/Utils.cs
72
src/Utils.cs
@@ -1,11 +1,81 @@
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.IO.Pipes;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text.Json.Nodes;
|
||||
using YaeAchievement.Win32;
|
||||
using static YaeAchievement.Win32.OpenFileFlags;
|
||||
|
||||
namespace YaeAchievement;
|
||||
|
||||
public static class Utils {
|
||||
|
||||
public static void LoadConfig() {
|
||||
var conf = JsonNode.Parse(File.ReadAllText(GlobalVars.ConfigFileName))!;
|
||||
var path = conf["genshinPath"];
|
||||
if (path == null || CheckGamePathValid(path.GetValue<string>())) {
|
||||
GlobalVars.GamePath = SelectGameExecutable();
|
||||
conf["genshinPath"] = GlobalVars.GamePath;
|
||||
File.WriteAllText(GlobalVars.ConfigFileName, conf.ToJsonString());
|
||||
} else {
|
||||
GlobalVars.GamePath = path.GetValue<string>();
|
||||
}
|
||||
}
|
||||
|
||||
private static bool CheckGamePathValid(string path) {
|
||||
var dir = Path.GetDirectoryName(path)!;
|
||||
return File.Exists($"{dir}/UnityPlayer.dll") && File.Exists($"{dir}/mhypbase.dll");
|
||||
}
|
||||
|
||||
private static string SelectGameExecutable() {
|
||||
var fnPtr = Marshal.AllocHGlobal(32768);
|
||||
var ofn = new OpenFileName {
|
||||
file = fnPtr,
|
||||
size = Marshal.SizeOf<OpenFileName>(),
|
||||
owner = Native.GetConsoleWindow(),
|
||||
flags = Explorer | NoNetworkButton | FileMustExist | NoChangeDir,
|
||||
title = "选择主程序",
|
||||
filter = "国服/国际服主程序 (YuanShen/GenshinImpact.exe)\0YuanShen.exe;GenshinImpact.exe\0",
|
||||
maxFile = 32768
|
||||
};
|
||||
if(!Native.GetOpenFileName(ofn)) {
|
||||
var err = Native.CommDlgExtendedError();
|
||||
if (err != 0) {
|
||||
throw new SystemException($"Dialog error: {err}");
|
||||
}
|
||||
Console.WriteLine("操作被取消");
|
||||
Environment.Exit(0);
|
||||
}
|
||||
var path = Marshal.PtrToStringAuto(fnPtr)!;
|
||||
Marshal.FreeHGlobal(fnPtr);
|
||||
return path;
|
||||
}
|
||||
|
||||
public static void CheckGenshinIsRunning() {
|
||||
Process.EnterDebugMode();
|
||||
foreach (var process in Process.GetProcesses()) {
|
||||
if (process.ProcessName is "GenshinImpact" or "YuanShen") {
|
||||
Console.WriteLine("原神正在运行,请关闭后重试");
|
||||
Environment.Exit(301);
|
||||
}
|
||||
}
|
||||
Process.LeaveDebugMode();
|
||||
}
|
||||
|
||||
public static void InstallExitHook() {
|
||||
AppDomain.CurrentDomain.ProcessExit += (_, _) => {
|
||||
Console.WriteLine("按任意键退出");
|
||||
Console.ReadKey();
|
||||
};
|
||||
}
|
||||
|
||||
public static void InstallExceptionHook() {
|
||||
AppDomain.CurrentDomain.UnhandledException += (_, e) => {
|
||||
Console.WriteLine(e.ExceptionObject.ToString());
|
||||
Console.WriteLine("发生错误,请联系开发者以获取帮助");
|
||||
Environment.Exit(-1);
|
||||
};
|
||||
}
|
||||
|
||||
// ReSharper disable once UnusedMethodReturnValue.Global
|
||||
public static Thread StartAndWaitResult(string exePath, Func<string, bool> onReceive) {
|
||||
@@ -31,7 +101,7 @@ public static class Utils {
|
||||
proc.EnableRaisingEvents = true;
|
||||
proc.Exited += (_, _) => {
|
||||
if (GlobalVars.UnexpectedExit) {
|
||||
Console.WriteLine($"Game process exit at {proc.ExitTime:HH:mm:ss}");
|
||||
Console.WriteLine("游戏进程异常退出");
|
||||
Environment.Exit(114514);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -41,7 +41,7 @@ public static class Native {
|
||||
[SuppressMessage("Globalization", "CA2101:指定对 P/Invoke 字符串参数进行封送处理")]
|
||||
public static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling=true)]
|
||||
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
|
||||
public static extern IntPtr VirtualAllocEx(
|
||||
IntPtr hProcess,
|
||||
IntPtr lpAddress,
|
||||
@@ -50,7 +50,7 @@ public static class Native {
|
||||
MemoryProtection flProtect
|
||||
);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError=true, ExactSpelling=true)]
|
||||
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
|
||||
public static extern bool VirtualFreeEx(IntPtr hProcess, IntPtr lpAddress, int dwSize, AllocationType dwFreeType);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
@@ -71,4 +71,14 @@ public static class Native {
|
||||
uint dwCreationFlags,
|
||||
out IntPtr lpThreadId
|
||||
);
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
public static extern IntPtr GetConsoleWindow();
|
||||
|
||||
[DllImport("comdlg32.dll", SetLastError = true)]
|
||||
public static extern int CommDlgExtendedError();
|
||||
|
||||
[DllImport("comdlg32.dll", SetLastError = true, CharSet = CharSet.Auto)]
|
||||
public static extern bool GetOpenFileName([In, Out] OpenFileName ofn);
|
||||
|
||||
}
|
||||
|
||||
9
src/Win32/OpenFileFlags.cs
Normal file
9
src/Win32/OpenFileFlags.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
namespace YaeAchievement.Win32;
|
||||
|
||||
[Flags]
|
||||
public enum OpenFileFlags : uint {
|
||||
Explorer = 0x00080000,
|
||||
NoChangeDir = 0x00000008,
|
||||
FileMustExist = 0x00001000,
|
||||
NoNetworkButton = 0x00020000,
|
||||
}
|
||||
32
src/Win32/OpenFileName.cs
Normal file
32
src/Win32/OpenFileName.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// ReSharper disable MemberCanBePrivate.Global
|
||||
// ReSharper disable FieldCanBeMadeReadOnly.Global
|
||||
|
||||
namespace YaeAchievement.Win32;
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
|
||||
public struct OpenFileName {
|
||||
public int size;
|
||||
public IntPtr owner;
|
||||
public IntPtr instance;
|
||||
public string filter;
|
||||
public IntPtr customFilter;
|
||||
public int maxCustFilter;
|
||||
public int filterIndex;
|
||||
public IntPtr file;
|
||||
public int maxFile;
|
||||
public IntPtr fileTitle;
|
||||
public int maxFileTitle;
|
||||
public string initialDir;
|
||||
public string title;
|
||||
public OpenFileFlags flags;
|
||||
public short fileOffset;
|
||||
public short fileExtension;
|
||||
public string defExt;
|
||||
public IntPtr custData;
|
||||
public IntPtr hook;
|
||||
public string templateName;
|
||||
public IntPtr reservedPtr;
|
||||
public int reservedInt;
|
||||
public int flagsEx;
|
||||
}
|
||||
Reference in New Issue
Block a user