From ec10f77c4cf93fc53cc48e10d03fad3672c9defb Mon Sep 17 00:00:00 2001 From: Meivyn <793322+Meivyn@users.noreply.github.com> Date: Sat, 19 Nov 2022 05:36:12 -0500 Subject: [PATCH] Refactor verbose argument handling --- IPA.Injector/Injector.cs | 41 ++++++++++++++++------------- IPA.Loader/Logging/ConsoleWindow.cs | 23 ++++++++++------ docs/articles/command-line.md | 15 +++++------ 3 files changed, 43 insertions(+), 36 deletions(-) diff --git a/IPA.Injector/Injector.cs b/IPA.Injector/Injector.cs index 5332e2ca..65d00fe5 100644 --- a/IPA.Injector/Injector.cs +++ b/IPA.Injector/Injector.cs @@ -45,23 +45,8 @@ namespace IPA.Injector _ = args; try { - var cmd = Environment.GetCommandLineArgs(); - - if (cmd.Contains("--verbose")) - { - var arg = string.Empty; - - for (var i = 0; i < cmd.Length; i++) - { - if (cmd[i] == "-pid" && cmd.Length > i + 1) - { - arg = cmd[i + 1]; - break; - } - } - - WinConsole.Initialize(uint.TryParse(arg, out uint pid) ? pid : WinConsole.AttachParent); - } + var arguments = Environment.GetCommandLineArgs(); + MaybeInitializeConsole(arguments); SetupLibraryLoading(); @@ -70,7 +55,7 @@ namespace IPA.Injector // this is weird, but it prevents Mono from having issues loading the type. // IMPORTANT: NO CALLS TO ANY LOGGER CAN HAPPEN BEFORE THIS var unused = StandardLogger.PrintFilter; - #region // Above hack explaination + #region // Above hack explanation /* * Due to an unknown bug in the version of Mono that Unity uses, if the first access to StandardLogger * is a call to a constructor, then Mono fails to load the type correctly. However, if the first access is to @@ -80,7 +65,7 @@ namespace IPA.Injector Default.Debug("Initializing logger"); - SelfConfig.ReadCommandLine(Environment.GetCommandLineArgs()); + SelfConfig.ReadCommandLine(arguments); SelfConfig.Load(); DisabledConfig.Load(); @@ -117,6 +102,24 @@ namespace IPA.Injector } } + private static void MaybeInitializeConsole(string[] arguments) + { + var i = 0; + while (i < arguments.Length) + { + if (arguments[i++] == "--verbose") + { + if (i == arguments.Length) + { + WinConsole.Initialize(WinConsole.AttachParent); + return; + } + + WinConsole.Initialize(int.TryParse(arguments[i], out var processId) ? processId : WinConsole.AttachParent); + } + } + } + private static void EnsureDirectories() { string path; diff --git a/IPA.Loader/Logging/ConsoleWindow.cs b/IPA.Loader/Logging/ConsoleWindow.cs index 9450a1a1..2b6fd020 100644 --- a/IPA.Loader/Logging/ConsoleWindow.cs +++ b/IPA.Loader/Logging/ConsoleWindow.cs @@ -22,11 +22,11 @@ namespace IPA.Logging internal static bool IsInitialized; - public static void Initialize(uint pid, bool alwaysCreateNewConsole = false) + public static void Initialize(int processId, bool alwaysCreateNewConsole = false) { bool consoleAttached = true; if (alwaysCreateNewConsole - || (!AttachConsole(pid) + || (!AttachConsole(processId) && Marshal.GetLastWin32Error() != ErrorAccessDenied)) { consoleAttached = AllocConsole(); @@ -62,7 +62,7 @@ namespace IPA.Logging if (!SetConsoleMode(handle, mode)) { UseVTEscapes = false; - Console.Error.WriteLine("Could not enable VT100 escape code processing (maybe you're running an old Windows?): " + + Console.Error.WriteLine("Could not enable VT100 escape code processing (maybe you're running an old Windows?): " + new Win32Exception(Marshal.GetLastWin32Error()).Message); } } @@ -106,12 +106,14 @@ namespace IPA.Logging return null; } -#region Win API Functions and Constants + #region Win API Functions and Constants + [DllImport("kernel32.dll", EntryPoint = "AllocConsole", SetLastError = true, CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] + [DefaultDllImportSearchPaths(DllImportSearchPath.System32)] private static extern bool AllocConsole(); [DllImport("kernel32.dll", @@ -119,13 +121,15 @@ namespace IPA.Logging SetLastError = true, CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] - private static extern bool AttachConsole(uint dwProcessId); + [DefaultDllImportSearchPaths(DllImportSearchPath.System32)] + private static extern bool AttachConsole(int dwProcessId); [DllImport("kernel32.dll", EntryPoint = "CreateFileW", SetLastError = true, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)] + [DefaultDllImportSearchPaths(DllImportSearchPath.System32)] private static extern IntPtr CreateFileW( string lpFileName, uint dwDesiredAccess, @@ -137,12 +141,15 @@ namespace IPA.Logging ); [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] + [DefaultDllImportSearchPaths(DllImportSearchPath.System32)] private static extern bool GetConsoleMode(IntPtr hConsoleHandle, out uint lpMode); [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] + [DefaultDllImportSearchPaths(DllImportSearchPath.System32)] private static extern bool SetConsoleMode(IntPtr hConsoleHandle, uint dwMode); [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] + [DefaultDllImportSearchPaths(DllImportSearchPath.System32)] private static extern IntPtr GetStdHandle(int nStdHandle); private const uint EnableVTProcessing = 0x0004; @@ -154,9 +161,9 @@ namespace IPA.Logging private const uint OpenExisting = 0x00000003; private const uint FileAttributeNormal = 0x80; private const uint ErrorAccessDenied = 5; - - public const uint AttachParent = 0xFFFFFFFF; -#endregion + internal const int AttachParent = -1; + + #endregion } } \ No newline at end of file diff --git a/docs/articles/command-line.md b/docs/articles/command-line.md index 2e3b6822..5d2b2bd1 100644 --- a/docs/articles/command-line.md +++ b/docs/articles/command-line.md @@ -26,16 +26,18 @@ Here's a quick list of what they are and what they do. > Makes a console appear with log information at startup. > - > Optionally, to start Beat Saber with an external console, an explicit `-pid` can be specified. This allows the game to be launched without being interrupted by Steam's "Allow game launch?" popup when directly launching `Beat Saber.exe` with arguments. + > Optionally, an explicit process ID can be specified to start the game with an external console. This allows it to be launched without being interrupted by Steam's "Allow game launch?" popup when directly launching `Beat Saber.exe` with arguments. > - Using PowerShell: + > > ```powershell - > .\steam -applaunch 620980 --verbose -pid $PID + > .\steam -applaunch 620980 --verbose $PID > ``` + > > - Using Command Prompt: + > > ```powershell - > powershell -c ".\steam -applaunch 620980 --verbose -pid (Get-CimInstance Win32_Process -Filter ProcessId=$PID).ParentProcessId" + > powershell -c ".\steam -applaunch 620980 --verbose (Get-CimInstance Win32_Process -Filter ProcessId=$PID).ParentProcessId" > ``` - > - `--debug` @@ -45,7 +47,6 @@ Here's a quick list of what they are and what they do. > This option also forces BSIPA to show all debug messages in the console, as well as where they were called. > > This overrides the config settings `Debug.ShowDebug` and `Debug.ShowCallSource`. - > - `--trace` @@ -53,7 +54,6 @@ Here's a quick list of what they are and what they do. > When this or the config option is used, they are added and logged with the same rules as Debug messages. > > This overrides the config setting `Debug.ShowTrace`. - > - `--mono-debug` @@ -63,7 +63,6 @@ Here's a quick list of what they are and what they do. > debugger server running on port 10000 on `localhost`. > > Implies `--debug`. - > - `--server` @@ -72,7 +71,6 @@ Here's a quick list of what they are and what they do. > When paired with `--mono-debug`, this option makes the Mono soft debugger act in server mode. It begins listening on > port 10000 on any address, and will pause startup (with no window) until a debugger is connected. I recommend using > SDB, but that is a command line debugger and a lot of people don't care for those. - > - `--no-yeet` @@ -83,7 +81,6 @@ Here's a quick list of what they are and what they do. > behaviour is disabled. > > Overrides the config setting `YeetMods`. - > - `--condense-logs`