diff --git a/App.config b/App.config
new file mode 100644
index 0000000..193aecc
--- /dev/null
+++ b/App.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/App.cs b/App.cs
new file mode 100644
index 0000000..478c567
--- /dev/null
+++ b/App.cs
@@ -0,0 +1,263 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Windows.Forms;
+using System.Diagnostics;
+using System.Linq;
+using System.Text.RegularExpressions;
+using System.Management;
+using System.ComponentModel;
+using System.Net.Http;
+using System.Threading.Tasks;
+using System.Text;
+
+namespace fix_lcu_window_bin
+{
+ internal class App
+ {
+ [DllImport("User32.dll", EntryPoint = "FindWindow")]
+ public extern static IntPtr FindWindow(string lpClassName, string lpWindowName);
+
+ [DllImport("User32.dll", EntryPoint = "FindWindowEx")]
+ public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpClassName, string lpWindowName);
+
+ [DllImport("user32.dll", CharSet = CharSet.Auto)]
+ private static extern int SetWindowPos(IntPtr hWnd, int hWndInsertAfter, int x, int y, int Width, int Height, int flags);
+
+ [DllImport("user32.dll")]
+ private static extern uint GetDpiForWindow([In] IntPtr hmonitor);
+
+ // 取commandline
+ private static string GetCommandLineByProcessId(int processId)
+ {
+ try
+ {
+ return GetCommandLineArgsCore();
+ }
+ catch (Win32Exception ex) when ((uint)ex.ErrorCode == 0x80004005)
+ {
+ return string.Empty;
+ }
+ catch (InvalidOperationException)
+ {
+ return string.Empty;
+ }
+
+ string GetCommandLineArgsCore()
+ {
+ using (var searcher = new ManagementObjectSearcher(
+ "SELECT CommandLine FROM Win32_Process WHERE ProcessId = " + processId))
+ using (var objects = searcher.Get())
+ {
+ var @object = objects.Cast().SingleOrDefault();
+ return @object?["CommandLine"]?.ToString() ?? "";
+ }
+ }
+ }
+
+ private static int GetProcessId(String processName)
+ {
+ Process[] processes = Process.GetProcesses();
+ int iProcessId = 0;
+
+ foreach (Process p in processes)
+ {
+ if (p.ProcessName == processName)
+ {
+ iProcessId = p.Id;
+ break;
+ }
+ }
+
+ return iProcessId;
+ }
+
+ private static (bool Available, int Port, string Token, string Protocol) CommandLineParser(string command)
+ {
+ Regex installAuthToken = new Regex(@"""--remoting-auth-token=(.*?)""");
+ Regex installAppPort = new Regex(@"""--app-port=(.*?)""");
+
+ var portMatch = installAppPort.Match(command);
+ var tokenMatch = installAuthToken.Match(command);
+
+ if (portMatch.Success && tokenMatch.Success)
+ {
+ return (true, int.Parse(portMatch.Groups[1].Value), tokenMatch.Groups[1].Value, "https");
+ }
+
+ return (false, 0, null, null);
+ }
+
+ private static async Task GetLeagueClientZoom(int Port, String Token)
+ {
+
+ String address = "https://127.0.0.1:" + Port + "/riotclient/zoom-scale";
+
+ WebRequestHandler handler = new WebRequestHandler();
+ HttpClient client = new HttpClient(handler);
+
+ handler.ServerCertificateValidationCallback = delegate { return true; };
+ client.DefaultRequestHeaders.Add("Accept", "*/*");
+ client.DefaultRequestHeaders.Add("Authorization", "Basic " + Convert.ToBase64String(Encoding.ASCII.GetBytes("riot:" + Token)));
+ try
+ {
+ HttpResponseMessage response = await client.GetAsync(address);
+ response.EnsureSuccessStatusCode();
+
+ return double.Parse(await response.Content.ReadAsStringAsync());
+ }
+ catch
+ {
+ return -1;
+ }
+ }
+
+ private static async Task RestartClientUx(int Port, String Token)
+ {
+
+ string address = "https://127.0.0.1:" + Port + "/riotclient/kill-and-restart-ux";
+
+ WebRequestHandler handler = new WebRequestHandler();
+ HttpClient client = new HttpClient(handler);
+
+ handler.ServerCertificateValidationCallback = delegate { return true; };
+ client.DefaultRequestHeaders.Add("Accept", "*/*");
+ client.DefaultRequestHeaders.Add("Authorization", "Basic " + Convert.ToBase64String(Encoding.ASCII.GetBytes("riot:" + Token)));
+ try
+ {
+ HttpResponseMessage response = await client.PostAsync(address, new StringContent(""));
+ response.EnsureSuccessStatusCode();
+
+ return true;
+ }
+ catch
+ {
+ return false;
+ }
+ }
+
+ private static void emitExit()
+ {
+ Console.WriteLine("按任意键退出...");
+ Console.ReadKey();
+ }
+
+ private static async Task MethodPlanA()
+ {
+ var LeagueClientUxCommandLine = GetCommandLineByProcessId(GetProcessId("LeagueClientUx"));
+ var LeagueClientUxArgs = CommandLineParser(LeagueClientUxCommandLine);
+
+ if (!LeagueClientUxArgs.Available)
+ {
+ Console.WriteLine("Can't find LeagueClientUx process.");
+ emitExit();
+ return;
+ }
+
+ IntPtr pLeagueClientWindowHWnd = FindWindow("RCLIENT", "League of Legends");
+ IntPtr pLeagueClientWindowCefHWnd = FindWindowEx(pLeagueClientWindowHWnd, IntPtr.Zero, "CefBrowserWindow", null);
+
+ if (pLeagueClientWindowHWnd == IntPtr.Zero || pLeagueClientWindowCefHWnd == IntPtr.Zero)
+ {
+ Console.WriteLine("Can't find LeagueClient window.");
+ emitExit();
+ return;
+ }
+
+ double fLeagueClientZoom = await GetLeagueClientZoom(LeagueClientUxArgs.Port, LeagueClientUxArgs.Token);
+ double fScreenDpi = GetDpiForWindow(pLeagueClientWindowHWnd) / 96.0;
+ int iScreenWidth = Screen.PrimaryScreen.Bounds.Width;
+ int iScreenHeight = Screen.PrimaryScreen.Bounds.Height;
+
+ if (fLeagueClientZoom == -1)
+ {
+ Console.WriteLine("Can't get original zoom of LeagueClientUx");
+ emitExit();
+ return;
+ }
+
+ int iTargetWindowWidth = (int)(1280 * fLeagueClientZoom);
+ int iTargetWindowHeight = (int)(720 * fLeagueClientZoom);
+
+ Console.WriteLine("LeagueClientPort: " + LeagueClientUxArgs.Port);
+ Console.WriteLine("LeagueClientAuthtoken: " + LeagueClientUxArgs.Token);
+ Console.WriteLine("LeagueClientOriginZoom: " + fLeagueClientZoom);
+ Console.WriteLine("LeagueClientWindowHWnd: " + pLeagueClientWindowHWnd);
+ Console.WriteLine("LeagueClientWindowCefHWnd: " + pLeagueClientWindowCefHWnd);
+ Console.WriteLine("ScreenWidth: " + iScreenWidth * fScreenDpi);
+ Console.WriteLine("ScreenHeight: " + iScreenHeight * fScreenDpi);
+ Console.WriteLine("ScreenDpi: " + fScreenDpi);
+ Console.WriteLine("TargetWindowWidth: " + iTargetWindowWidth);
+ Console.WriteLine("TargetWindowHeight: " + iTargetWindowHeight);
+
+ Console.WriteLine("-----------------------------");
+ Console.WriteLine("客户端修复成功!");
+ Console.WriteLine("-----------------------------");
+
+ SetWindowPos(pLeagueClientWindowHWnd, 0, (iScreenWidth - iTargetWindowWidth) / 2, (iScreenHeight - iTargetWindowHeight) / 2, iTargetWindowWidth, iTargetWindowHeight, 0x0040);
+ SetWindowPos(pLeagueClientWindowCefHWnd, 0, 0, 0, iTargetWindowWidth, iTargetWindowHeight, 0x0040);
+ }
+
+ private static async Task MethodPlanB()
+ {
+ var LeagueClientUxCommandLine = GetCommandLineByProcessId(GetProcessId("LeagueClientUx"));
+ var LeagueClientUxArgs = CommandLineParser(LeagueClientUxCommandLine);
+
+ if (!LeagueClientUxArgs.Available)
+ {
+ Console.WriteLine("Can't find LeagueClientUx process.");
+ emitExit();
+ return;
+ }
+
+ if (!await RestartClientUx(LeagueClientUxArgs.Port, LeagueClientUxArgs.Token))
+ {
+ Console.WriteLine("Failed to reload LeagueClientUx.");
+ emitExit();
+ return;
+ }
+
+ Console.WriteLine("LeagueClientPort: " + LeagueClientUxArgs.Port);
+ Console.WriteLine("LeagueClientAuthtoken: " + LeagueClientUxArgs.Token);
+
+ Console.WriteLine("-----------------------------");
+ Console.WriteLine("客户端修复成功!");
+ Console.WriteLine("-----------------------------");
+ }
+
+ static void Main(string[] args)
+ {
+ Console.WriteLine("-----------------------------");
+ Console.WriteLine("Bilibili: Butter_Cookies");
+ Console.WriteLine("Github: https://github.com/LeagueTavern/fix-lcu-window");
+ Console.WriteLine("Code by LeagueTavern");
+ Console.WriteLine("-----------------------------");
+ Console.WriteLine("选择修复模式:");
+ Console.WriteLine("[1]: 通过 窗口句柄 修复客户端");
+ Console.WriteLine("[2]: 通过 LCUAPI 热重载客户端");
+ Console.WriteLine("-----------------------------");
+ Console.WriteLine("输入您想选择的修复模式 [1]:");
+
+ String strUserInput = Console.ReadLine();
+ int iUserChoice;
+
+ Console.WriteLine("-----------------------------");
+
+
+ if (String.IsNullOrWhiteSpace(strUserInput) || !int.TryParse(strUserInput, out iUserChoice))
+ {
+ iUserChoice = 1;
+ }
+
+ switch (iUserChoice)
+ {
+ case 1:
+ MethodPlanA().Wait();
+ break;
+ case 2:
+ MethodPlanB().Wait();
+ break;
+ }
+ emitExit();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..88b4dbc
--- /dev/null
+++ b/Properties/AssemblyInfo.cs
@@ -0,0 +1,19 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+
+[assembly: AssemblyTitle("Fix-LCU-Window")]
+[assembly: AssemblyDescription("Fix League of Legends client window.")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("LeagueTavern")]
+[assembly: AssemblyProduct("fix-lcu-window")]
+[assembly: AssemblyCopyright("Copyright © LeagueTavern 2023")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+[assembly: ComVisible(false)]
+[assembly: Guid("3787836b-68c8-4026-bc2d-833e1752e7f6")]
+
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/app.manifest b/app.manifest
new file mode 100644
index 0000000..75867c2
--- /dev/null
+++ b/app.manifest
@@ -0,0 +1,79 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/fix-lcu-window-bin.csproj b/fix-lcu-window-bin.csproj
new file mode 100644
index 0000000..22b429d
--- /dev/null
+++ b/fix-lcu-window-bin.csproj
@@ -0,0 +1,88 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {3787836B-68C8-4026-BC2D-833E1752E7F6}
+ Exe
+ fix_lcu_window_bin
+ fix-lcu-window-bin
+ v4.8
+ 512
+ true
+ true
+ publish\
+ true
+ Disk
+ false
+ Foreground
+ 7
+ Days
+ false
+ false
+ true
+ 0
+ 1.0.0.%2a
+ false
+ false
+ true
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+ app.manifest
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ False
+ Microsoft .NET Framework 4.8 %28x86 和 x64%29
+ true
+
+
+ False
+ .NET Framework 3.5 SP1
+ false
+
+
+
+
\ No newline at end of file
diff --git a/fix-lcu-window-bin.sln b/fix-lcu-window-bin.sln
new file mode 100644
index 0000000..03b1efc
--- /dev/null
+++ b/fix-lcu-window-bin.sln
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.7.34031.279
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "fix-lcu-window-bin", "fix-lcu-window-bin.csproj", "{3787836B-68C8-4026-BC2D-833E1752E7F6}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {3787836B-68C8-4026-BC2D-833E1752E7F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {3787836B-68C8-4026-BC2D-833E1752E7F6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {3787836B-68C8-4026-BC2D-833E1752E7F6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {3787836B-68C8-4026-BC2D-833E1752E7F6}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {D844A625-55BC-4BAD-96BD-39B9B33DA694}
+ EndGlobalSection
+EndGlobal
diff --git a/readme.md b/readme.md
new file mode 100644
index 0000000..4c12410
--- /dev/null
+++ b/readme.md
@@ -0,0 +1,2 @@
+# Fix-League-Client-Update-Window
+本项目适用于修复《英雄联盟》客户端因不明原因导致的尺寸异常问题。
\ No newline at end of file