Browse Source

Merge pull request #97 from Meivyn/console-tweaks

Console tweaks and fixes
pull/99/head
nike4613 1 year ago
committed by GitHub
parent
commit
3f25a0c7f7
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 69 additions and 67 deletions
  1. +25
    -6
      IPA.Injector/Injector.cs
  2. +31
    -53
      IPA.Loader/Logging/ConsoleWindow.cs
  3. +13
    -8
      docs/articles/command-line.md

+ 25
- 6
IPA.Injector/Injector.cs View File

@ -45,8 +45,8 @@ namespace IPA.Injector
_ = args; _ = args;
try try
{ {
if (Environment.GetCommandLineArgs().Contains("--verbose"))
WinConsole.Initialize();
var arguments = Environment.GetCommandLineArgs();
MaybeInitializeConsole(arguments);
SetupLibraryLoading(); SetupLibraryLoading();
@ -55,8 +55,8 @@ namespace IPA.Injector
// this is weird, but it prevents Mono from having issues loading the type. // this is weird, but it prevents Mono from having issues loading the type.
// IMPORTANT: NO CALLS TO ANY LOGGER CAN HAPPEN BEFORE THIS // IMPORTANT: NO CALLS TO ANY LOGGER CAN HAPPEN BEFORE THIS
var unused = StandardLogger.PrintFilter; 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 * 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 * is a call to a constructor, then Mono fails to load the type correctly. However, if the first access is to
* the above static property (or maybe any, but I don't really know) it behaves as expected and works fine. * the above static property (or maybe any, but I don't really know) it behaves as expected and works fine.
@ -65,7 +65,7 @@ namespace IPA.Injector
Default.Debug("Initializing logger"); Default.Debug("Initializing logger");
SelfConfig.ReadCommandLine(Environment.GetCommandLineArgs());
SelfConfig.ReadCommandLine(arguments);
SelfConfig.Load(); SelfConfig.Load();
DisabledConfig.Load(); DisabledConfig.Load();
@ -102,6 +102,25 @@ 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 int processId) ? processId : WinConsole.AttachParent);
return;
}
}
}
private static void EnsureDirectories() private static void EnsureDirectories()
{ {
string path; string path;
@ -256,7 +275,7 @@ namespace IPA.Injector
using var ascModule = VirtualizedModule.Load(ascPath); using var ascModule = VirtualizedModule.Load(ascPath);
ascModule.Virtualize(cAsmName, () => bkp?.Add(ascPath)); ascModule.Virtualize(cAsmName, () => bkp?.Add(ascPath));
} }
catch (Exception e)
catch (Exception e)
{ {
Logging.Logger.Injector.Error($"Could not virtualize {ascPath}"); Logging.Logger.Injector.Error($"Could not virtualize {ascPath}");
if (SelfConfig.Debug_.ShowHandledErrorStackTraces_) if (SelfConfig.Debug_.ShowHandledErrorStackTraces_)


+ 31
- 53
IPA.Loader/Logging/ConsoleWindow.cs View File

@ -22,14 +22,12 @@ namespace IPA.Logging
internal static bool IsInitialized; internal static bool IsInitialized;
public static void Initialize(bool alwaysCreateNewConsole = false)
public static void Initialize(int processId, bool alwaysCreateNewConsole = false)
{ {
bool consoleAttached = true;
if (alwaysCreateNewConsole
|| (AttachConsole(AttachParent) == 0
&& Marshal.GetLastWin32Error() != ErrorAccessDenied))
bool consoleAttached;
if (alwaysCreateNewConsole || !(consoleAttached = AttachConsole(processId)))
{ {
consoleAttached = AllocConsole() != 0;
consoleAttached = AllocConsole();
} }
if (consoleAttached) if (consoleAttached)
@ -39,7 +37,7 @@ namespace IPA.Logging
} }
} }
public static void InitializeStreams()
private static void InitializeStreams()
{ {
InitializeOutStream(); InitializeOutStream();
InitializeInStream(); InitializeInStream();
@ -62,7 +60,7 @@ namespace IPA.Logging
if (!SetConsoleMode(handle, mode)) if (!SetConsoleMode(handle, mode))
{ {
UseVTEscapes = false; 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); new Win32Exception(Marshal.GetLastWin32Error()).Message);
} }
} }
@ -87,18 +85,11 @@ namespace IPA.Logging
private static FileStream CreateFileStream(string name, uint win32DesiredAccess, uint win32ShareMode, private static FileStream CreateFileStream(string name, uint win32DesiredAccess, uint win32ShareMode,
FileAccess dotNetFileAccess, out SafeFileHandle handle) FileAccess dotNetFileAccess, out SafeFileHandle handle)
{ {
var file = new SafeFileHandle(CreateFileW(name, win32DesiredAccess, win32ShareMode, IntPtr.Zero, OpenExisting, FileAttributeNormal, IntPtr.Zero), true);
var file = new SafeFileHandle(CreateFile(name, win32DesiredAccess, win32ShareMode, IntPtr.Zero, OpenExisting, FileAttributeNormal, IntPtr.Zero), true);
if (!file.IsInvalid) if (!file.IsInvalid)
{ {
handle = file; handle = file;
#if NET4
var fs = new FileStream(file, dotNetFileAccess); var fs = new FileStream(file, dotNetFileAccess);
#elif NET3
#pragma warning disable CS0618
// this is marked obsolete, and shouldn't need to be used, but the constructor used in .NET 4 doesn't exist in Unity's mscorlib.dll
var fs = new FileStream(file.DangerousGetHandle(), dotNetFileAccess);
#pragma warning restore
#endif
return fs; return fs;
} }
@ -106,43 +97,31 @@ namespace IPA.Logging
return null; return null;
} }
#region Win API Functions and Constants
[DllImport("kernel32.dll",
EntryPoint = "AllocConsole",
SetLastError = true,
CharSet = CharSet.Auto,
CallingConvention = CallingConvention.StdCall)]
private static extern int AllocConsole();
[DllImport("kernel32.dll",
EntryPoint = "AttachConsole",
SetLastError = true,
CharSet = CharSet.Auto,
CallingConvention = CallingConvention.StdCall)]
private static extern uint AttachConsole(uint dwProcessId);
[DllImport("kernel32.dll",
EntryPoint = "CreateFileW",
SetLastError = true,
CharSet = CharSet.Unicode,
CallingConvention = CallingConvention.StdCall)]
private static extern IntPtr CreateFileW(
string lpFileName,
uint dwDesiredAccess,
uint dwShareMode,
IntPtr lpSecurityAttributes,
uint dwCreationDisposition,
uint dwFlagsAndAttributes,
IntPtr hTemplateFile
);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
#region Win API Functions and Constants
[DllImport("kernel32.dll")]
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
private static extern bool AllocConsole();
[DllImport("kernel32.dll")]
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
private static extern bool AttachConsole(int dwProcessId);
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
private static extern IntPtr CreateFile(string lpFileName, uint dwDesiredAccess, uint dwShareMode,
IntPtr lpSecurityAttributes, uint dwCreationDisposition, uint dwFlagsAndAttributes, IntPtr hTemplateFile);
[DllImport("kernel32.dll", SetLastError = true)]
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
private static extern bool GetConsoleMode(IntPtr hConsoleHandle, out uint lpMode); private static extern bool GetConsoleMode(IntPtr hConsoleHandle, out uint lpMode);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[DllImport("kernel32.dll", SetLastError = true)]
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
private static extern bool SetConsoleMode(IntPtr hConsoleHandle, uint dwMode); private static extern bool SetConsoleMode(IntPtr hConsoleHandle, uint dwMode);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[DllImport("kernel32.dll")]
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
private static extern IntPtr GetStdHandle(int nStdHandle); private static extern IntPtr GetStdHandle(int nStdHandle);
private const uint EnableVTProcessing = 0x0004; private const uint EnableVTProcessing = 0x0004;
@ -153,10 +132,9 @@ namespace IPA.Logging
private const uint FileShareWrite = 0x00000002; private const uint FileShareWrite = 0x00000002;
private const uint OpenExisting = 0x00000003; private const uint OpenExisting = 0x00000003;
private const uint FileAttributeNormal = 0x80; private const uint FileAttributeNormal = 0x80;
private const uint ErrorAccessDenied = 5;
private const uint AttachParent = 0xFFFFFFFF;
#endregion
internal const int AttachParent = -1;
#endregion
} }
} }

+ 13
- 8
docs/articles/command-line.md View File

@ -26,6 +26,16 @@ Here's a quick list of what they are and what they do.
> Makes a console appear with log information at startup. > Makes a console appear with log information at startup.
> >
> Optionally, an explicit process ID can be specified to start the game with an external console. This allows it to be
> launched via Steam without being interrupted by its "Allow game launch?" if launched directly from the `.exe`.
>
> Example for Beat Saber using PowerShell:
>
> ```
> .\steam.exe -applaunch 620980 --verbose $PID
> ```
>
> Do note that this isn't going to work from an elevated terminal.
- `--debug` - `--debug`
@ -35,15 +45,13 @@ 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 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`. > This overrides the config settings `Debug.ShowDebug` and `Debug.ShowCallSource`.
>
- `--trace` - `--trace`
> Enables trace level messages. By default, they do not ever enter the message queue, and thus cost almost nothing. > Enables trace level messages. By default, they do not ever enter the message queue, and thus cost almost nothing.
> When this or the config option is used, they are added and logged with the same rules as Debug messages. > 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`. > This overrides the config setting `Debug.ShowTrace`.
>
- `--mono-debug` - `--mono-debug`
@ -53,7 +61,6 @@ Here's a quick list of what they are and what they do.
> debugger server running on port 10000 on `localhost`. > debugger server running on port 10000 on `localhost`.
> >
> Implies `--debug`. > Implies `--debug`.
>
- `--server` - `--server`
@ -62,7 +69,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 > 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 > 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. > SDB, but that is a command line debugger and a lot of people don't care for those.
>
- `--no-yeet` - `--no-yeet`
@ -73,7 +79,6 @@ Here's a quick list of what they are and what they do.
> behaviour is disabled. > behaviour is disabled.
> >
> Overrides the config setting `YeetMods`. > Overrides the config setting `YeetMods`.
>
- `--condense-logs` - `--condense-logs`
@ -85,11 +90,11 @@ Here's a quick list of what they are and what they do.
> Overrides the config setting `Debug.CondenseModLogs`. > Overrides the config setting `Debug.CondenseModLogs`.
- `--plugin-logs` - `--plugin-logs`
> Causes each plugins' log messages to be written to files in their own folder for ease of debugging. > Causes each plugins' log messages to be written to files in their own folder for ease of debugging.
> >
> This was the default through 4.1.6, however is now disabled by default. > This was the default through 4.1.6, however is now disabled by default.
> >
> Overrides the config setting `Debug.CreateModLogs`. > Overrides the config setting `Debug.CreateModLogs`.
*** ***

Loading…
Cancel
Save