diff --git a/res/App.Designer.cs b/res/App.Designer.cs index a31960e..d49deae 100644 --- a/res/App.Designer.cs +++ b/res/App.Designer.cs @@ -246,6 +246,15 @@ namespace YaeAchievement.res { } } + /// + /// Looks up a localized string similar to No write permission on {0}.. + /// + internal static string NoWritePermission { + get { + return ResourceManager.GetString("NoWritePermission", resourceCulture); + } + } + /// /// Looks up a localized string similar to Press any key to exit.. /// diff --git a/res/App.resx b/res/App.resx index 4f6ee1f..cbef798 100644 --- a/res/App.resx +++ b/res/App.resx @@ -126,4 +126,7 @@ Input a number (0-5): Please update genshin and retry. + + No write permission on {0}. + \ No newline at end of file diff --git a/res/App.zh.resx b/res/App.zh.resx index 6e64cb2..af01949 100644 --- a/res/App.zh.resx +++ b/res/App.zh.resx @@ -117,4 +117,7 @@ 请将原神更新至最新版本后重试 + + 无法写入文件,请更换软件所在目录后重试 + \ No newline at end of file diff --git a/src/Export.cs b/src/Export.cs index 44cb1cd..cbe48b6 100644 --- a/src/Export.cs +++ b/src/Export.cs @@ -85,8 +85,9 @@ public static class Export { // ReSharper disable once InconsistentNaming private static void ToUIAFJson(AchievementAllDataNotify data) { var path = Path.GetFullPath($"uiaf-{DateTime.Now:yyyyMMddHHmmss}.json"); - File.WriteAllText(path, JsonSerializer.Serialize(ExportToUIAFApp(data))); - Console.WriteLine(App.ExportToFileSuccess, path); + if (TryWriteToFile(path, JsonSerializer.Serialize(ExportToUIAFApp(data)))) { + Console.WriteLine(App.ExportToFileSuccess, path); + } } private static void ToPaimon(AchievementAllDataNotify data) { @@ -105,8 +106,9 @@ public static class Export { ["achievement"] = output.OrderBy(pair => pair.Key).ToDictionary(pair => pair.Key, pair => pair.Value) }; var path = Path.GetFullPath($"export-{DateTime.Now:yyyyMMddHHmmss}-paimon.json"); - File.WriteAllText(path, JsonSerializer.Serialize(final)); - Console.WriteLine(App.ExportToFileSuccess, path); + if (TryWriteToFile(path, JsonSerializer.Serialize(final))) { + Console.WriteLine(App.ExportToFileSuccess, path); + } } private static void ToSeelie(AchievementAllDataNotify data) { @@ -120,8 +122,9 @@ public static class Export { ["achievements"] = output.OrderBy(pair => pair.Key).ToDictionary(pair => pair.Key, pair => pair.Value) }; var path = Path.GetFullPath($"export-{DateTime.Now:yyyyMMddHHmmss}-seelie.json"); - File.WriteAllText(path, JsonSerializer.Serialize(final)); - Console.WriteLine(App.ExportToFileSuccess, path); + if (TryWriteToFile(path, JsonSerializer.Serialize(final))) { + Console.WriteLine(App.ExportToFileSuccess, path); + } } // ReSharper disable once InconsistentNaming @@ -151,9 +154,10 @@ public static class Export { return item.JoinToString(","); })); var path = Path.GetFullPath($"achievement-{DateTime.Now:yyyyMMddHHmmss}.csv"); - File.WriteAllText(path, $"\uFEFF{string.Join("\n", output)}"); - Console.WriteLine(App.ExportToFileSuccess, path); - Process.Start("explorer.exe", $"{Path.GetDirectoryName(path)}"); + if (TryWriteToFile(path, $"\uFEFF{string.Join("\n", output)}")) { + Console.WriteLine(App.ExportToFileSuccess, path); + Process.Start("explorer.exe", $"{Path.GetDirectoryName(path)}"); + } } private static void ToXunkong(AchievementAllDataNotify data) { @@ -169,10 +173,12 @@ public static class Export { private static void ToRawJson(AchievementAllDataNotify data) { var path = Path.GetFullPath($"export-{DateTime.Now:yyyyMMddHHmmss}-raw.json"); - File.WriteAllText(path, JsonSerializer.Serialize(data, new JsonSerializerOptions { + var text = JsonSerializer.Serialize(data, new JsonSerializerOptions { WriteIndented = true - })); - Console.WriteLine(App.ExportToFileSuccess, path); + }); + if (TryWriteToFile(path, text)) { + Console.WriteLine(App.ExportToFileSuccess, path); + } } // ReSharper disable once InconsistentNaming @@ -228,4 +234,14 @@ public static class Export { AppCenter.TrackCrash(ex, false); return ex.NativeErrorCode; } + + private static bool TryWriteToFile(string path, string contents) { + try { + File.WriteAllText(path, contents); + return true; + } catch (UnauthorizedAccessException) { + Console.WriteLine(App.NoWritePermission, path); + return false; + } + } } diff --git a/src/Injector.cs b/src/Injector.cs index 814551a..4714786 100644 --- a/src/Injector.cs +++ b/src/Injector.cs @@ -7,6 +7,7 @@ using Windows.Win32.System.Threading; namespace YaeAchievement; public static class Injector { + public static unsafe bool CreateProcess(string path, out HANDLE hProc, out HANDLE hThread, out uint pid) { Span cmdLines = stackalloc char[1]; // "\0" var si = new STARTUPINFOW { diff --git a/src/Program.cs b/src/Program.cs index e693b21..958a756 100644 --- a/src/Program.cs +++ b/src/Program.cs @@ -9,8 +9,8 @@ TryDisableQuickEdit(); InstallExitHook(); InstallExceptionHook(); -await CheckVcRuntime(); CheckSelfIsRunning(); +await CheckVcRuntime(); CheckGenshinIsRunning(); Console.WriteLine(@"----------------------------------------------------"); diff --git a/src/Utils.cs b/src/Utils.cs index 8f25977..cb5f236 100644 --- a/src/Utils.cs +++ b/src/Utils.cs @@ -50,7 +50,7 @@ public static class Utils { cacheFile.Write(responseBytes, etag); } return responseBytes; - } catch (Exception e) { + } catch (Exception e) when(e is SocketException or TaskCanceledException) { Console.WriteLine(App.NetworkError, e.Message); Environment.Exit(-1); return null!; @@ -73,8 +73,8 @@ public static class Utils { if (Native.OpenClipboard(HWND.Null)) { Native.EmptyClipboard(); - HANDLE hGlobal = (HANDLE)Marshal.AllocHGlobal((text.Length + 1) * 2); - IntPtr hPtr = (IntPtr)Native.GlobalLock(hGlobal); + var hGlobal = (HANDLE) Marshal.AllocHGlobal((text.Length + 1) * 2); + var hPtr = (nint) Native.GlobalLock(hGlobal); Marshal.Copy(text.ToCharArray(), 0, hPtr, text.Length); Native.GlobalUnlock(hPtr); Native.SetClipboardData(13, hGlobal); @@ -121,15 +121,17 @@ public static class Utils { } public static void CheckSelfIsRunning() { - 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); + 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(); + Process.LeaveDebugMode(); + } catch (Win32Exception) {} } // ReSharper disable once UnusedMethodReturnValue.Global @@ -162,7 +164,7 @@ public static class Utils { foreach (var process in Process.GetProcesses()) { if (process.ProcessName is "GenshinImpact" or "YuanShen" && !process.HasExited - && process.MainWindowHandle != IntPtr.Zero + && process.MainWindowHandle != nint.Zero ) { Console.WriteLine(App.GenshinIsRunning, process.Id); Environment.Exit(301); @@ -212,8 +214,9 @@ public static class Utils { #if DEBUG return true; #else + if (!File.Exists(path)) return false; var hash = File.ReadAllBytes(path).MD5Hash(); - return File.Exists(path) && (hash == _updateInfo.CurrentCNGameHash || hash == _updateInfo.CurrentOSGameHash); + return hash == _updateInfo.CurrentCNGameHash || hash == _updateInfo.CurrentOSGameHash; #endif } @@ -282,8 +285,6 @@ public static class Utils { th.Start(); return th; } - - #pragma warning disable CA1416 public static async Task CheckVcRuntime() { using var root = Registry.LocalMachine; @@ -301,7 +302,14 @@ public static class Utils { if (!installed) { Console.WriteLine(App.VcRuntimeDownload); var pkgPath = Path.Combine(GlobalVars.DataPath, "vc_redist.x64.exe"); - var bytes = await CHttpClient.GetByteArrayAsync("https://aka.ms/vs/17/release/vc_redist.x64.exe"); + byte[] bytes; + try { + bytes = await CHttpClient.GetByteArrayAsync("https://aka.ms/vs/17/release/vc_redist.x64.exe"); + } catch (Exception e) when(e is SocketException or TaskCanceledException) { + Console.WriteLine(App.NetworkError, e.Message); + Environment.Exit(-1); + return; + } await File.WriteAllBytesAsync(pkgPath, bytes); Console.WriteLine(App.VcRuntimeInstalling); using var process = new Process {