From 40269410c5468ea81087514fcfa9108022b5686b Mon Sep 17 00:00:00 2001 From: HolographicHat Date: Mon, 23 Jun 2025 00:03:12 +0800 Subject: [PATCH] fix sentry#2707 --- YaeAchievement/res/App.Designer.cs | 9 ++++ YaeAchievement/res/App.resx | 3 ++ YaeAchievement/res/App.zh.resx | 3 ++ YaeAchievement/src/Utilities/GameProcess.cs | 51 +++++++++++---------- YaeAchievement/src/Utils.cs | 4 +- 5 files changed, 45 insertions(+), 25 deletions(-) diff --git a/YaeAchievement/res/App.Designer.cs b/YaeAchievement/res/App.Designer.cs index e5366bc..1cc7302 100644 --- a/YaeAchievement/res/App.Designer.cs +++ b/YaeAchievement/res/App.Designer.cs @@ -347,6 +347,15 @@ namespace YaeAchievement.res { } } + /// + /// Looks up a localized string similar to Load failed. Please retry. ({0} {1} {2}). + /// + internal static string LoadLibraryFail { + get { + return ResourceManager.GetString("LoadLibraryFail", resourceCulture); + } + } + /// /// Looks up a localized string similar to Network error:. /// diff --git a/YaeAchievement/res/App.resx b/YaeAchievement/res/App.resx index 95594f7..02e7386 100644 --- a/YaeAchievement/res/App.resx +++ b/YaeAchievement/res/App.resx @@ -181,4 +181,7 @@ The process cannot access the file '{0}' because it is being used by another process. Please restart your computer and try again. + + Load failed. Please retry. ({0} {1} {2}) + \ No newline at end of file diff --git a/YaeAchievement/res/App.zh.resx b/YaeAchievement/res/App.zh.resx index 1653239..62f3376 100644 --- a/YaeAchievement/res/App.zh.resx +++ b/YaeAchievement/res/App.zh.resx @@ -174,4 +174,7 @@ 文件 {0} 被其它程序占用,请 重启电脑 或 解除文件占用 后重试。 + + 加载失败,请重试({0} {1} {2}) + \ No newline at end of file diff --git a/YaeAchievement/src/Utilities/GameProcess.cs b/YaeAchievement/src/Utilities/GameProcess.cs index d925586..f52a168 100644 --- a/YaeAchievement/src/Utilities/GameProcess.cs +++ b/YaeAchievement/src/Utilities/GameProcess.cs @@ -1,8 +1,9 @@ -using System.Runtime.InteropServices; +using System.ComponentModel; +using System.Runtime.InteropServices; using Windows.Win32; using Windows.Win32.Foundation; using Windows.Win32.System.Threading; - +using Spectre.Console; using static Windows.Win32.System.Memory.VIRTUAL_ALLOCATION_TYPE; using static Windows.Win32.System.Memory.PAGE_PROTECTION_FLAGS; using static Windows.Win32.System.Memory.VIRTUAL_FREE_TYPE; @@ -50,29 +51,33 @@ public sealed unsafe class GameProcess { } public void LoadLibrary(string libPath) { - var hKrnl32 = NativeLibrary.Load("kernel32"); - var mLoadLibraryW = NativeLibrary.GetExport(hKrnl32, "LoadLibraryW"); - var libPathLen = (uint) libPath.Length * sizeof(char); - var lpLibPath = Native.VirtualAllocEx(Handle, null, libPathLen + 2, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); - if (lpLibPath == null) { - throw new ApplicationException($"VirtualAllocEx fail: {Marshal.GetLastPInvokeErrorMessage()}"); - } - fixed (void* lpBuffer = libPath) { - if (!Native.WriteProcessMemory(Handle, lpLibPath, lpBuffer, libPathLen)) { - throw new ApplicationException($"WriteProcessMemory fail: {Marshal.GetLastPInvokeErrorMessage()}"); + try { + var hKrnl32 = NativeLibrary.Load("kernel32"); + var mLoadLibraryW = NativeLibrary.GetExport(hKrnl32, "LoadLibraryW"); + var libPathLen = (uint) libPath.Length * sizeof(char); + var lpLibPath = Native.VirtualAllocEx(Handle, null, libPathLen + 2, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); + if (lpLibPath == null) { + throw new Win32Exception { Data = { { "api", "VirtualAllocEx" } } }; } + fixed (void* lpBuffer = libPath) { + if (!Native.WriteProcessMemory(Handle, lpLibPath, lpBuffer, libPathLen)) { + throw new Win32Exception { Data = { { "api", "WriteProcessMemory" } } }; + } + } + var lpStartAddress = (delegate*unmanaged[Stdcall]) mLoadLibraryW; // THREAD_START_ROUTINE + var hThread = Native.CreateRemoteThread(Handle, null, 0, lpStartAddress, lpLibPath, 0); + if (hThread.IsNull) { + throw new Win32Exception { Data = { { "api", "CreateRemoteThread" } } }; + } + if (Native.WaitForSingleObject(hThread, 2000) == 0) { + Native.VirtualFreeEx(Handle, lpLibPath, 0, MEM_RELEASE); + } + Native.CloseHandle(hThread); + } catch (Win32Exception e) { + _ = Terminate(0); + AnsiConsole.WriteLine(App.LoadLibraryFail, e.Data["api"]!, e.NativeErrorCode, e.Message); + Environment.Exit(-1); } - var lpStartAddress = (delegate*unmanaged[Stdcall]) mLoadLibraryW; // THREAD_START_ROUTINE - var hThread = Native.CreateRemoteThread(Handle, null, 0, lpStartAddress, lpLibPath, 0); - if (hThread.IsNull) { - var error = Marshal.GetLastPInvokeErrorMessage(); - Native.VirtualFreeEx(Handle, lpLibPath, 0, MEM_RELEASE); - throw new ApplicationException($"CreateRemoteThread fail: {error}"); - } - if (Native.WaitForSingleObject(hThread, 2000) == 0) { - Native.VirtualFreeEx(Handle, lpLibPath, 0, MEM_RELEASE); - } - Native.CloseHandle(hThread); } public bool ResumeMainThread() => Native.ResumeThread(MainThreadHandle) != 0xFFFFFFFF; diff --git a/YaeAchievement/src/Utils.cs b/YaeAchievement/src/Utils.cs index 474772b..2472dc6 100644 --- a/YaeAchievement/src/Utils.cs +++ b/YaeAchievement/src/Utils.cs @@ -207,6 +207,8 @@ public static class Utils { // ReSharper disable once UnusedMethodReturnValue.Global public static void StartAndWaitResult(string exePath, Dictionary> handlers, Action onFinish) { _proc = new GameProcess(exePath); + _proc.LoadLibrary(GlobalVars.LibFilePath); + _proc.ResumeMainThread(); _proc.OnExit += () => { if (_isUnexpectedExit) { _proc = null; @@ -214,8 +216,6 @@ public static class Utils { Environment.Exit(114514); } }; - _proc.LoadLibrary(GlobalVars.LibFilePath); - _proc.ResumeMainThread(); AnsiConsole.WriteLine(App.GameLoading, _proc.Id); Task.Run(() => { using var stream = new NamedPipeServerStream(GlobalVars.PipeName);