Skip to content

Commit

Permalink
添加项目文件。
Browse files Browse the repository at this point in the history
  • Loading branch information
Coooookies committed Dec 10, 2023
1 parent a04179a commit 045bca3
Show file tree
Hide file tree
Showing 7 changed files with 482 additions and 0 deletions.
6 changes: 6 additions & 0 deletions App.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8" />
</startup>
</configuration>
263 changes: 263 additions & 0 deletions App.cs
Original file line number Diff line number Diff line change
@@ -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<ManagementBaseObject>().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<double> 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<bool> 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();
}
}
}
19 changes: 19 additions & 0 deletions Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -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")]
79 changes: 79 additions & 0 deletions app.manifest
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
<!-- UAC 清单选项
如果想要更改 Windows 用户帐户控制级别,请使用
以下节点之一替换 requestedExecutionLevel 节点。
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
<requestedExecutionLevel level="highestAvailable" uiAccess="false" />
指定 requestedExecutionLevel 元素将禁用文件和注册表虚拟化。
如果你的应用程序需要此虚拟化来实现向后兼容性,则移除此
元素。
-->
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
</requestedPrivileges>
</security>
</trustInfo>

<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- 设计此应用程序与其一起工作且已针对此应用程序进行测试的
Windows 版本的列表。取消评论适当的元素,
Windows 将自动选择最兼容的环境。 -->

<!-- Windows Vista -->
<!--<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" />-->

<!-- Windows 7 -->
<!--<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />-->

<!-- Windows 8 -->
<!--<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />-->

<!-- Windows 8.1 -->
<!--<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />-->

<!-- Windows 10 -->
<!--<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />-->

</application>
</compatibility>

<!-- 指示该应用程序可感知 DPI 且 Windows 在 DPI 较高时将不会对其进行
自动缩放。Windows Presentation Foundation (WPF)应用程序自动感知 DPI,无需
选择加入。选择加入此设置的 Windows 窗体应用程序(面向 .NET Framework 4.6)还应
在其 app.config 中将 "EnableWindowsFormsHighDpiAutoResizing" 设置设置为 "true"。
将应用程序设为感知长路径。请参阅 https://docs.microsoft.com/windows/win32/fileio/maximum-file-path-limitation -->
<!--
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
<longPathAware xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">true</longPathAware>
</windowsSettings>
</application>
-->

<!-- 启用 Windows 公共控件和对话框的主题(Windows XP 和更高版本) -->
<!--
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
processorArchitecture="*"
publicKeyToken="6595b64144ccf1df"
language="*"
/>
</dependentAssembly>
</dependency>
-->

</assembly>
Loading

0 comments on commit 045bca3

Please sign in to comment.