diff --git a/IPA.Loader/Logging/ConsoleWindow.cs b/IPA.Loader/Logging/ConsoleWindow.cs index 5dbc7462..ca10d578 100644 --- a/IPA.Loader/Logging/ConsoleWindow.cs +++ b/IPA.Loader/Logging/ConsoleWindow.cs @@ -37,7 +37,7 @@ namespace IPA.Logging } } - public static void InitializeStreams() + private static void InitializeStreams() { InitializeOutStream(); InitializeInStream(); @@ -85,18 +85,11 @@ namespace IPA.Logging private static FileStream CreateFileStream(string name, uint win32DesiredAccess, uint win32ShareMode, 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) { handle = file; -#if NET4 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; } @@ -106,47 +99,28 @@ namespace IPA.Logging #region Win API Functions and Constants - [DllImport("kernel32.dll", - EntryPoint = "AllocConsole", - SetLastError = true, - CharSet = CharSet.Auto, - CallingConvention = CallingConvention.StdCall)] + [DllImport("kernel32.dll")] [DefaultDllImportSearchPaths(DllImportSearchPath.System32)] private static extern bool AllocConsole(); - [DllImport("kernel32.dll", - EntryPoint = "AttachConsole", - SetLastError = true, - CharSet = CharSet.Auto, - CallingConvention = CallingConvention.StdCall)] + [DllImport("kernel32.dll")] [DefaultDllImportSearchPaths(DllImportSearchPath.System32)] private static extern bool AttachConsole(int dwProcessId); - [DllImport("kernel32.dll", - EntryPoint = "CreateFileW", - SetLastError = true, - CharSet = CharSet.Unicode, - CallingConvention = CallingConvention.StdCall)] + [DllImport("kernel32.dll", CharSet = CharSet.Unicode)] [DefaultDllImportSearchPaths(DllImportSearchPath.System32)] - 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)] + 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); - [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); - [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] + [DllImport("kernel32.dll")] [DefaultDllImportSearchPaths(DllImportSearchPath.System32)] private static extern IntPtr GetStdHandle(int nStdHandle); @@ -158,7 +132,6 @@ namespace IPA.Logging private const uint FileShareWrite = 0x00000002; private const uint OpenExisting = 0x00000003; private const uint FileAttributeNormal = 0x80; - private const uint ErrorAccessDenied = 5; internal const int AttachParent = -1; diff --git a/IPA.Loader/Logging/StdoutInterceptorPipes.cs b/IPA.Loader/Logging/StdoutInterceptorPipes.cs index 3d484a98..699c5ded 100644 --- a/IPA.Loader/Logging/StdoutInterceptorPipes.cs +++ b/IPA.Loader/Logging/StdoutInterceptorPipes.cs @@ -1,7 +1,6 @@ using System; using System.IO.Pipes; using System.Runtime.InteropServices; -using System.Runtime.Versioning; using System.Text; using System.Threading; @@ -17,8 +16,8 @@ namespace IPA.Logging public static void Initialize() { - InitializePipe(STD_OUTPUT_HANDLE); - InitializePipe(STD_ERROR_HANDLE); + InitializePipe(StdOutputHandle); + InitializePipe(StdErrorHandle); } private static void InitializePipe(int stdHandle) @@ -36,7 +35,7 @@ namespace IPA.Logging { return new Thread(() => { - NamedPipeServerStream pipeServer = new(pipeName, PipeDirection.In); + var pipeServer = new NamedPipeServerStream(pipeName, PipeDirection.In); try { @@ -46,11 +45,14 @@ namespace IPA.Logging var buffer = new byte[1024]; while (pipeServer.IsConnected) { + // TODO: Figure out why this line is absolutely needed + // to avoid blocking the main thread when ShouldRedirectStdHandles is false. + var length = pipeServer.Read(buffer, 0, buffer.Length); if (ShouldRedirectStdHandles) { // Separate method to avoid a BadImageFormatException when accessing StdoutInterceptor early. // This happens because the Harmony DLL is not loaded at this point. - Redirect(pipeServer, buffer, stdHandle); + WriteToInterceptor(length , buffer, stdHandle); } } } @@ -68,7 +70,7 @@ namespace IPA.Logging { return new Thread(() => { - NamedPipeClientStream pipeClient = new(".", pipeName, PipeDirection.Out); + var pipeClient = new NamedPipeClientStream(".", pipeName, PipeDirection.Out); try { @@ -91,19 +93,17 @@ namespace IPA.Logging }); } - private static void Redirect(NamedPipeServerStream server, byte[] buffer, int stdHandle) + private static void WriteToInterceptor(int length, byte[] buffer, int stdHandle) { - var charsRead = server.Read(buffer, 0, buffer.Length); - var interceptor = stdHandle == STD_OUTPUT_HANDLE ? StdoutInterceptor.Stdout : StdoutInterceptor.Stderr; - interceptor!.Write(Encoding.UTF8.GetString(buffer, 0, charsRead)); + var interceptor = stdHandle == StdOutputHandle ? StdoutInterceptor.Stdout : StdoutInterceptor.Stderr; + interceptor!.Write(Encoding.UTF8.GetString(buffer, 0, length)); } - [DllImport("kernel32", CharSet = CharSet.Auto, SetLastError = true)] + [DllImport("kernel32.dll")] [DefaultDllImportSearchPaths(DllImportSearchPath.System32)] - [ResourceExposure(ResourceScope.Process)] private static extern bool SetStdHandle(int nStdHandle, IntPtr hHandle); - private const int STD_OUTPUT_HANDLE = -11; - private const int STD_ERROR_HANDLE = -12; + private const int StdOutputHandle = -11; + private const int StdErrorHandle = -12; } } \ No newline at end of file diff --git a/docs/articles/command-line.md b/docs/articles/command-line.md index 019e50cc..fc08bc13 100644 --- a/docs/articles/command-line.md +++ b/docs/articles/command-line.md @@ -43,7 +43,6 @@ Here's a quick list of what they are and what they do. > > Do note that this isn't going to work from an elevated terminal. - - `--debug` > Enables the loading of debug information in Mono. The debugging information must be in the portable PDB format, @@ -54,7 +53,7 @@ Here's a quick list of what they are and what they do. > This overrides the config settings `Debug.ShowDebug` and `Debug.ShowCallSource`. - `--trace` - + > 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. > @@ -97,11 +96,11 @@ Here's a quick list of what they are and what they do. > Overrides the config setting `Debug.CondenseModLogs`. - `--plugin-logs` - + > 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. > > Overrides the config setting `Debug.CreateModLogs`. - + ***