This commit is contained in:
HolographicHat
2022-06-13 17:43:02 +08:00
parent e847d4c80e
commit bbe7c2cd03
6 changed files with 145 additions and 13 deletions

View File

@@ -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";
}

View File

@@ -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)!;

View File

@@ -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);
}
};

View File

@@ -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);
}

View 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
View 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;
}