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