diff --git a/YaeAchievement/YaeAchievement.csproj b/YaeAchievement/YaeAchievement.csproj
index 3ad0769..b32503f 100644
--- a/YaeAchievement/YaeAchievement.csproj
+++ b/YaeAchievement/YaeAchievement.csproj
@@ -29,6 +29,7 @@
all
runtime; build; native; contentfiles; analyzers; buildtransitive
+
diff --git a/YaeAchievement/src/AppConfig.cs b/YaeAchievement/src/AppConfig.cs
index 4285045..c8f071f 100644
--- a/YaeAchievement/src/AppConfig.cs
+++ b/YaeAchievement/src/AppConfig.cs
@@ -1,5 +1,6 @@
using System.Text.RegularExpressions;
using YaeAchievement.res;
+using YaeAchievement.Utilities;
namespace YaeAchievement;
@@ -7,6 +8,8 @@ public static partial class AppConfig {
public static string GamePath { get; private set; } = null!;
+ private static readonly string[] ProductNames = [ "原神", "Genshin Impact" ];
+
internal static void Load(string argumentPath) {
if (argumentPath != "auto" && File.Exists(argumentPath)) {
GamePath = argumentPath;
@@ -21,25 +24,16 @@ public static partial class AppConfig {
}
}
var appDataPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
- var cnLogPath = Path.Combine(appDataPath, @"..\LocalLow\miHoYo\原神\output_log.txt");
- var osLogPath = Path.Combine(appDataPath, @"..\LocalLow\miHoYo\Genshin Impact\output_log.txt");
- if (!File.Exists(cnLogPath) && !File.Exists(osLogPath)) {
+ var logPath = ProductNames
+ .Select(name => $"{appDataPath}/../LocalLow/miHoYo/{name}/output_log.txt")
+ .Where(File.Exists)
+ .MaxBy(File.GetLastWriteTime);
+ if (logPath == null) {
throw new ApplicationException(App.ConfigNeedStartGenshin);
}
- string finalLogPath;
- if (!File.Exists(osLogPath)) {
- finalLogPath = cnLogPath;
- } else if (!File.Exists(cnLogPath)) {
- finalLogPath = osLogPath;
- } else {
- var cnLastWriteTime = File.GetLastWriteTime(cnLogPath);
- var osLastWriteTime = File.GetLastWriteTime(osLogPath);
- finalLogPath = cnLastWriteTime > osLastWriteTime ? cnLogPath : osLogPath;
- }
- GamePath = GetGamePathFromLogFile(finalLogPath)
- ?? GetGamePathFromLogFile($"{finalLogPath}.last")
+ GamePath = GetGamePathFromLogFile(logPath)
+ ?? GetGamePathFromLogFile($"{logPath}.last")
?? throw new ApplicationException(App.ConfigNeedStartGenshin);
- pathCacheFile.Write(GamePath);
}
private static string? GetGamePathFromLogFile(string path) {
@@ -51,7 +45,7 @@ public static partial class AppConfig {
var content = File.ReadAllText(copiedLogFilePath);
try {
File.Delete(copiedLogFilePath);
- } catch (Exception) { /* ignore */}
+ } catch (Exception) { /* ignore */ }
var matchResult = GamePathRegex().Match(content);
if (!matchResult.Success) {
return null;
diff --git a/YaeAchievement/src/GlobalVars.cs b/YaeAchievement/src/GlobalVars.cs
index ee88893..334c7a9 100644
--- a/YaeAchievement/src/GlobalVars.cs
+++ b/YaeAchievement/src/GlobalVars.cs
@@ -1,6 +1,7 @@
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using Proto;
+using YaeAchievement.Utilities;
namespace YaeAchievement;
diff --git a/YaeAchievement/src/Program.cs b/YaeAchievement/src/Program.cs
index e6bafaf..6ba255e 100644
--- a/YaeAchievement/src/Program.cs
+++ b/YaeAchievement/src/Program.cs
@@ -1,56 +1,76 @@
-using System.Text;
+using System.Runtime.CompilerServices;
+using System.Text;
using System.Text.Json;
-using YaeAchievement;
+using Windows.Win32;
+using Windows.Win32.System.Console;
using YaeAchievement.Parsers;
using YaeAchievement.res;
using static YaeAchievement.Utils;
-Console.InputEncoding = Encoding.UTF8;
-Console.OutputEncoding = Encoding.UTF8;
+namespace YaeAchievement;
-TryDisableQuickEdit();
-InstallExitHook();
-InstallExceptionHook();
+internal static class Program {
-CheckSelfIsRunning();
-CheckGenshinIsRunning();
+ public static async Task Main(string[] args) {
-Console.WriteLine(@"----------------------------------------------------");
-Console.WriteLine(App.AppBanner, GlobalVars.AppVersionName);
-Console.WriteLine(@"https://github.com/HolographicHat/YaeAchievement");
-Console.WriteLine(@"----------------------------------------------------");
+ if (!new Mutex(true, @"Global\YaeMiku~uwu").WaitOne(0, false)) {
+ Console.WriteLine(App.AnotherInstance);
+ Environment.Exit(302);
+ }
-AppConfig.Load(args.GetOrNull(0) ?? "auto");
-Export.ExportTo = ToUIntOrNull(args.GetOrNull(1)) ?? uint.MaxValue;
+ InstallExitHook();
+ InstallExceptionHook();
-await CheckUpdate(ToBooleanOrFalse(args.GetOrNull(2)));
+ CheckGenshinIsRunning();
-var historyCache = GlobalVars.AchievementDataCache;
+ Console.WriteLine(@"----------------------------------------------------");
+ Console.WriteLine(App.AppBanner, GlobalVars.AppVersionName);
+ Console.WriteLine(@"https://github.com/HolographicHat/YaeAchievement");
+ Console.WriteLine(@"----------------------------------------------------");
-AchievementAllDataNotify? data = null;
-try {
- data = AchievementAllDataNotify.ParseFrom(historyCache.Read().Content.ToByteArray());
-} catch (Exception) { /* ignored */ }
+ AppConfig.Load(args.GetOrNull(0) ?? "auto");
+ Export.ExportTo = ToUIntOrNull(args.GetOrNull(1)) ?? uint.MaxValue;
-if (historyCache.LastWriteTime.AddMinutes(60) > DateTime.UtcNow && data != null) {
- Console.WriteLine(App.UsePreviousData);
- if (Console.ReadLine()?.ToUpper() is "Y" or "YES") {
- Export.Choose(data);
- return;
- }
-}
+ await CheckUpdate(ToBooleanOrFalse(args.GetOrNull(2)));
-StartAndWaitResult(AppConfig.GamePath, new Dictionary> {
- { 1, AchievementAllDataNotify.OnReceive },
- { 2, PlayerStoreNotify.OnReceive },
- { 100, PlayerPropNotify.OnReceive },
-}, () => {
+ var historyCache = GlobalVars.AchievementDataCache;
+
+ AchievementAllDataNotify? data = null;
+ try {
+ data = AchievementAllDataNotify.ParseFrom(historyCache.Read().Content.ToByteArray());
+ } catch (Exception) { /* ignored */ }
+
+ if (historyCache.LastWriteTime.AddMinutes(60) > DateTime.UtcNow && data != null) {
+ Console.WriteLine(App.UsePreviousData);
+ if (Console.ReadLine()?.ToUpper() is "Y" or "YES") {
+ Export.Choose(data);
+ return;
+ }
+ }
+
+ StartAndWaitResult(AppConfig.GamePath, new Dictionary> {
+ { 1, AchievementAllDataNotify.OnReceive },
+ { 2, PlayerStoreNotify.OnReceive },
+ { 100, PlayerPropNotify.OnReceive },
+ }, () => {
#if DEBUG
- PlayerPropNotify.OnFinish();
- File.WriteAllText("store_data.json", JsonSerializer.Serialize(PlayerStoreNotify.Instance, new JsonSerializerOptions {
- WriteIndented = true,
- DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull
- }));
+ PlayerPropNotify.OnFinish();
+ File.WriteAllText("store_data.json", JsonSerializer.Serialize(PlayerStoreNotify.Instance, new JsonSerializerOptions {
+ WriteIndented = true,
+ DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull
+ }));
#endif
- AchievementAllDataNotify.OnFinish();
-});
+ AchievementAllDataNotify.OnFinish();
+ });
+ }
+
+ [ModuleInitializer]
+ internal static unsafe void SetupConsole() {
+ var handle = Native.GetStdHandle(STD_HANDLE.STD_INPUT_HANDLE);
+ CONSOLE_MODE mode = default;
+ Native.GetConsoleMode(handle, &mode);
+ Native.SetConsoleMode(handle, mode & ~CONSOLE_MODE.ENABLE_QUICK_EDIT_MODE);
+ Console.InputEncoding = Console.OutputEncoding = Encoding.UTF8;
+ }
+
+}
diff --git a/YaeAchievement/src/CacheFile.cs b/YaeAchievement/src/Utilities/CacheFile.cs
similarity index 97%
rename from YaeAchievement/src/CacheFile.cs
rename to YaeAchievement/src/Utilities/CacheFile.cs
index 9096ddb..39f8ca2 100644
--- a/YaeAchievement/src/CacheFile.cs
+++ b/YaeAchievement/src/Utilities/CacheFile.cs
@@ -2,7 +2,7 @@
using Google.Protobuf;
using Proto;
-namespace YaeAchievement;
+namespace YaeAchievement.Utilities;
public class CacheFile(string identifier) {
diff --git a/YaeAchievement/src/Utils.cs b/YaeAchievement/src/Utils.cs
index 8672ca1..ae8d35f 100644
--- a/YaeAchievement/src/Utils.cs
+++ b/YaeAchievement/src/Utils.cs
@@ -7,9 +7,9 @@ using System.Net.Sockets;
using System.Runtime.InteropServices;
using Windows.Win32;
using Windows.Win32.Foundation;
-using Windows.Win32.System.Console;
using Proto;
using YaeAchievement.res;
+using YaeAchievement.Utilities;
namespace YaeAchievement;
@@ -68,8 +68,7 @@ public static class Utils {
}
public static unsafe void CopyToClipboard(string text) {
- if (Native.OpenClipboard(HWND.Null))
- {
+ if (Native.OpenClipboard(HWND.Null)) {
Native.EmptyClipboard();
var hGlobal = (HGLOBAL) Marshal.AllocHGlobal((text.Length + 1) * 2);
var hPtr = (nint) Native.GlobalLock(hGlobal);
@@ -78,9 +77,7 @@ public static class Utils {
Native.SetClipboardData(13, new HANDLE(hPtr));
Marshal.FreeHGlobal(hGlobal);
Native.CloseClipboard();
- }
- else
- {
+ } else {
throw new Win32Exception();
}
}
@@ -116,20 +113,6 @@ public static class Utils {
_updateInfo = info;
}
- public static void CheckSelfIsRunning() {
- try {
- Process.EnterDebugMode();
- var cur = Process.GetCurrentProcess();
- foreach (var process in Process.GetProcesses().Where(process => process.Id != cur.Id)) {
- if (process.ProcessName == cur.ProcessName) {
- Console.WriteLine(App.AnotherInstance);
- Environment.Exit(302);
- }
- }
- Process.LeaveDebugMode();
- } catch (Win32Exception) {}
- }
-
// ReSharper disable once UnusedMethodReturnValue.Global
public static bool ShellOpen(string path, string? args = null) {
try {
@@ -148,13 +131,6 @@ public static class Utils {
}
}
- // ReSharper disable once UnusedMethodReturnValue.Global
- public static unsafe bool TryDisableQuickEdit() {
- var handle = Native.GetStdHandle(STD_HANDLE.STD_INPUT_HANDLE);
- CONSOLE_MODE mode = default;
- return Native.GetConsoleMode(handle, &mode) && Native.SetConsoleMode(handle, mode & ~CONSOLE_MODE.ENABLE_QUICK_EDIT_MODE);
- }
-
public static void CheckGenshinIsRunning() {
Process.EnterDebugMode();
foreach (var process in Process.GetProcesses()) {