From d2afe06f5b0df612fba588b75e972549a1ae60cb Mon Sep 17 00:00:00 2001
From: Bepis <36346617+bbepis@users.noreply.github.com>
Date: Thu, 21 May 2020 03:06:34 +1000
Subject: [PATCH] Initial abstraction of console related calls
---
.../Logger/PreloaderLogWriter.cs | 5 +-
BepInEx.Preloader/Preloader.cs | 23 +--
BepInEx/BepInEx.csproj | 14 +-
BepInEx/Bootstrap/Chainloader.cs | 29 +--
BepInEx/Console/ConsoleManager.cs | 183 ++++++++++++++++++
.../ConsoleEncoding.Buffers.cs | 0
.../ConsoleEncoding.PInvoke.cs | 0
.../ConsoleEncoding/ConsoleEncoding.cs | 0
.../Windows}/ConsoleWindow.cs | 25 +--
.../{ConsoleUtil => Console/Windows}/Kon.cs | 30 ++-
.../Windows}/SafeConsole.cs | 0
BepInEx/Logging/ConsoleLogListener.cs | 5 +-
12 files changed, 239 insertions(+), 75 deletions(-)
create mode 100644 BepInEx/Console/ConsoleManager.cs
rename BepInEx/{ConsoleUtil => Console/Windows}/ConsoleEncoding/ConsoleEncoding.Buffers.cs (100%)
rename BepInEx/{ConsoleUtil => Console/Windows}/ConsoleEncoding/ConsoleEncoding.PInvoke.cs (100%)
rename BepInEx/{ConsoleUtil => Console/Windows}/ConsoleEncoding/ConsoleEncoding.cs (100%)
rename BepInEx/{ConsoleUtil => Console/Windows}/ConsoleWindow.cs (84%)
rename BepInEx/{ConsoleUtil => Console/Windows}/Kon.cs (79%)
rename BepInEx/{ConsoleUtil => Console/Windows}/SafeConsole.cs (100%)
diff --git a/BepInEx.Preloader/Logger/PreloaderLogWriter.cs b/BepInEx.Preloader/Logger/PreloaderLogWriter.cs
index ba2a7de..3465fd8 100644
--- a/BepInEx.Preloader/Logger/PreloaderLogWriter.cs
+++ b/BepInEx.Preloader/Logger/PreloaderLogWriter.cs
@@ -2,7 +2,6 @@
using System.Collections.Generic;
using System.IO;
using System.Text;
-using BepInEx.ConsoleUtil;
using BepInEx.Logging;
namespace BepInEx.Preloader
@@ -37,9 +36,9 @@ namespace BepInEx.Preloader
LogBuilder.Append(log);
- Kon.ForegroundColor = eventArgs.Level.GetConsoleColor();
+ ConsoleManager.SetConsoleColor(eventArgs.Level.GetConsoleColor());
ConsoleDirectWrite(log);
- Kon.ForegroundColor = ConsoleColor.Gray;
+ ConsoleManager.SetConsoleColor(ConsoleColor.Gray);
}
public void ConsoleDirectWrite(string value)
diff --git a/BepInEx.Preloader/Preloader.cs b/BepInEx.Preloader/Preloader.cs
index ec27ba9..348887a 100644
--- a/BepInEx.Preloader/Preloader.cs
+++ b/BepInEx.Preloader/Preloader.cs
@@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
-using System.Text;
using BepInEx.Configuration;
using BepInEx.Logging;
using BepInEx.Preloader.Patching;
@@ -12,7 +11,6 @@ using HarmonyLib;
using Mono.Cecil;
using Mono.Cecil.Cil;
using MonoMod.RuntimeDetour;
-using UnityInjector.ConsoleUtil;
using MethodAttributes = Mono.Cecil.MethodAttributes;
namespace BepInEx.Preloader
@@ -33,6 +31,7 @@ namespace BepInEx.Preloader
{
try
{
+ ConsoleManager.Initialize(false);
AllocateConsole();
bool bridgeInitialized = Utility.TryDo(() =>
@@ -57,7 +56,10 @@ namespace BepInEx.Preloader
Logger.Listeners.Add(PreloaderLog);
string consoleTile = $"BepInEx {typeof(Paths).Assembly.GetName().Version} - {Process.GetCurrentProcess().ProcessName}";
- ConsoleWindow.Title = consoleTile;
+
+ if (ConsoleManager.ConsoleActive)
+ ConsoleManager.SetConsoleTitle(consoleTile);
+
Logger.LogMessage(consoleTile);
//See BuildInfoAttribute for more information about this section.
@@ -112,7 +114,7 @@ namespace BepInEx.Preloader
PreloaderLog?.Dispose();
- if (!ConsoleWindow.IsAttached)
+ if (!ConsoleManager.ConsoleActive)
{
//if we've already attached the console, then the log will already be written to the console
AllocateConsole();
@@ -222,20 +224,13 @@ namespace BepInEx.Preloader
///
public static void AllocateConsole()
{
- if (!ConsoleWindow.ConfigConsoleEnabled.Value)
+ if (!ConsoleManager.ConfigConsoleEnabled.Value)
return;
try
{
- ConsoleWindow.Attach();
-
- var encoding = (uint)Encoding.UTF8.CodePage;
-
- if (ConsoleWindow.ConfigConsoleShiftJis.Value)
- encoding = 932;
-
- ConsoleEncoding.ConsoleCodePage = encoding;
- Console.OutputEncoding = ConsoleEncoding.GetEncoding(encoding);
+ ConsoleManager.CreateConsole();
+ ConsoleManager.SetConsoleEncoding();
}
catch (Exception ex)
{
diff --git a/BepInEx/BepInEx.csproj b/BepInEx/BepInEx.csproj
index 41bf15b..ae6ed98 100644
--- a/BepInEx/BepInEx.csproj
+++ b/BepInEx/BepInEx.csproj
@@ -62,6 +62,7 @@
+
@@ -72,12 +73,12 @@
-
-
-
-
-
-
+
+
+
+
+
+
@@ -110,5 +111,6 @@
+
\ No newline at end of file
diff --git a/BepInEx/Bootstrap/Chainloader.cs b/BepInEx/Bootstrap/Chainloader.cs
index d54440c..fa7be91 100644
--- a/BepInEx/Bootstrap/Chainloader.cs
+++ b/BepInEx/Bootstrap/Chainloader.cs
@@ -6,11 +6,9 @@ using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
-using System.Text;
using System.Text.RegularExpressions;
using Mono.Cecil;
using UnityEngine;
-using UnityInjector.ConsoleUtil;
using Logger = BepInEx.Logging.Logger;
namespace BepInEx.Bootstrap
@@ -69,20 +67,17 @@ namespace BepInEx.Bootstrap
}
// Start logging
- if (ConsoleWindow.ConfigConsoleEnabled.Value && startConsole)
+ if (ConsoleManager.ConfigConsoleEnabled.Value && startConsole)
{
- ConsoleWindow.Attach();
+ ConsoleManager.CreateConsole();
Logger.Listeners.Add(new ConsoleLogListener());
}
// Fix for standard output getting overwritten by UnityLogger
- if (ConsoleWindow.StandardOut != null)
+ if (ConsoleManager.ConsoleActive)
{
- Console.SetOut(ConsoleWindow.StandardOut);
-
- var encoding = ConsoleWindow.ConfigConsoleShiftJis.Value ? 932 : (uint)Encoding.UTF8.CodePage;
- ConsoleEncoding.ConsoleCodePage = encoding;
- Console.OutputEncoding = ConsoleEncoding.GetEncoding(encoding);
+ ConsoleManager.SetConsoleStreams();
+ ConsoleManager.SetConsoleEncoding();
}
Logger.Listeners.Add(new UnityLogListener());
@@ -227,7 +222,9 @@ namespace BepInEx.Bootstrap
try
{
var productNameProp = typeof(Application).GetProperty("productName", BindingFlags.Public | BindingFlags.Static);
- ConsoleWindow.Title = $"{CurrentAssemblyName} {CurrentAssemblyVersion} - {productNameProp?.GetValue(null, null) ?? Process.GetCurrentProcess().ProcessName}";
+
+ if (ConsoleManager.ConsoleActive)
+ ConsoleManager.SetConsoleTitle($"{CurrentAssemblyName} {CurrentAssemblyVersion} - {productNameProp?.GetValue(null, null) ?? Process.GetCurrentProcess().ProcessName}");
Logger.LogMessage("Chainloader started");
@@ -384,10 +381,14 @@ namespace BepInEx.Bootstrap
}
catch (Exception ex)
{
- ConsoleWindow.Attach();
+ try
+ {
+ ConsoleManager.CreateConsole();
+ }
+ catch { }
- Console.WriteLine("Error occurred starting the game");
- Console.WriteLine(ex.ToString());
+ Logger.LogFatal("Error occurred starting the game");
+ Logger.LogFatal(ex.ToString());
}
Logger.LogMessage("Chainloader startup complete");
diff --git a/BepInEx/Console/ConsoleManager.cs b/BepInEx/Console/ConsoleManager.cs
new file mode 100644
index 0000000..4d86eeb
--- /dev/null
+++ b/BepInEx/Console/ConsoleManager.cs
@@ -0,0 +1,183 @@
+using System;
+using System.IO;
+using System.Text;
+using BepInEx.Configuration;
+using BepInEx.ConsoleUtil;
+using UnityInjector.ConsoleUtil;
+
+namespace BepInEx
+{
+ public static class ConsoleManager
+ {
+ ///
+ /// True if an external console has been started, false otherwise.
+ ///
+ public static bool ConsoleActive { get; private set; }
+
+ ///
+ /// The stream that writes to the standard out stream of the process. Should never be null.
+ ///
+ public static TextWriter StandardOutStream { get; internal set; }
+
+ ///
+ /// The stream that writes to an external console. Null if no such console exists
+ ///
+ public static TextWriter ConsoleStream { get; internal set; }
+
+
+ public static void Initialize(bool active)
+ {
+ StandardOutStream = Console.Out;
+ Console.SetOut(StandardOutStream);
+ ConsoleActive = active;
+
+ switch (Environment.OSVersion.Platform)
+ {
+ case PlatformID.MacOSX:
+ case PlatformID.Unix:
+ {
+ ConsoleActive = true;
+ break;
+ }
+ }
+ }
+
+
+ public static void CreateConsole()
+ {
+ if (ConsoleActive)
+ return;
+
+ switch (Environment.OSVersion.Platform)
+ {
+ case PlatformID.Win32NT:
+ {
+ ConsoleWindow.Attach();
+ break;
+ }
+
+ default:
+ throw new PlatformNotSupportedException("Spawning a console is not currently supported on this platform");
+ }
+
+ SetConsoleStreams();
+
+ ConsoleActive = true;
+ }
+
+ public static void DetachConsole()
+ {
+ if (!ConsoleActive)
+ return;
+
+ switch (Environment.OSVersion.Platform)
+ {
+ case PlatformID.Win32NT:
+ {
+ ConsoleWindow.Detach();
+ break;
+ }
+
+ default:
+ throw new PlatformNotSupportedException("Spawning a console is not currently supported on this platform");
+ }
+
+ ConsoleActive = false;
+ }
+
+ public static void SetConsoleEncoding()
+ {
+ uint encoding = ConfigConsoleShiftJis.Value ? 932 : (uint)Encoding.UTF8.CodePage;
+
+ SetConsoleEncoding(encoding);
+ }
+
+ public static void SetConsoleEncoding(uint encodingCodePage)
+ {
+ if (!ConsoleActive)
+ throw new InvalidOperationException("Console is not currently active");
+
+ switch (Environment.OSVersion.Platform)
+ {
+ case PlatformID.Win32NT:
+ {
+ ConsoleEncoding.ConsoleCodePage = encodingCodePage;
+ Console.OutputEncoding = Encoding.GetEncoding((int)encodingCodePage);
+ break;
+ }
+
+ case PlatformID.MacOSX:
+ case PlatformID.Unix:
+ {
+ break;
+ }
+ }
+ }
+
+ public static void SetConsoleTitle(string title)
+ {
+ switch (Environment.OSVersion.Platform)
+ {
+ case PlatformID.Win32NT:
+ {
+ if (!ConsoleActive)
+ return;
+
+ ConsoleWindow.Title = title;
+ break;
+ }
+ }
+ }
+
+ public static void SetConsoleColor(ConsoleColor color)
+ {
+ switch (Environment.OSVersion.Platform)
+ {
+ case PlatformID.Win32NT:
+ {
+ if (!ConsoleActive)
+ return;
+
+ Kon.ForegroundColor = color;
+ break;
+ }
+ }
+
+ Console.ForegroundColor = color;
+ }
+
+ internal static void SetConsoleStreams()
+ {
+ switch (Environment.OSVersion.Platform)
+ {
+ case PlatformID.Win32NT:
+ {
+ Console.SetOut(ConsoleStream);
+ Console.SetError(ConsoleStream);
+ break;
+ }
+
+ case PlatformID.MacOSX:
+ case PlatformID.Unix:
+ {
+ // We do not have external consoles on Unix platforms.
+ // Set the console output to standard output
+
+ Console.SetOut(StandardOutStream);
+ Console.SetError(StandardOutStream);
+ break;
+ }
+ }
+ }
+
+ public static readonly ConfigEntry ConfigConsoleEnabled = ConfigFile.CoreConfig.Bind(
+ "Logging.Console", "Enabled",
+ false,
+ "Enables showing a console for log output.");
+
+ public static readonly ConfigEntry ConfigConsoleShiftJis = ConfigFile.CoreConfig.Bind(
+ "Logging.Console", "ShiftJisEncoding",
+ false,
+ "If true, console is set to the Shift-JIS encoding, otherwise UTF-8 encoding.");
+ }
+}
diff --git a/BepInEx/ConsoleUtil/ConsoleEncoding/ConsoleEncoding.Buffers.cs b/BepInEx/Console/Windows/ConsoleEncoding/ConsoleEncoding.Buffers.cs
similarity index 100%
rename from BepInEx/ConsoleUtil/ConsoleEncoding/ConsoleEncoding.Buffers.cs
rename to BepInEx/Console/Windows/ConsoleEncoding/ConsoleEncoding.Buffers.cs
diff --git a/BepInEx/ConsoleUtil/ConsoleEncoding/ConsoleEncoding.PInvoke.cs b/BepInEx/Console/Windows/ConsoleEncoding/ConsoleEncoding.PInvoke.cs
similarity index 100%
rename from BepInEx/ConsoleUtil/ConsoleEncoding/ConsoleEncoding.PInvoke.cs
rename to BepInEx/Console/Windows/ConsoleEncoding/ConsoleEncoding.PInvoke.cs
diff --git a/BepInEx/ConsoleUtil/ConsoleEncoding/ConsoleEncoding.cs b/BepInEx/Console/Windows/ConsoleEncoding/ConsoleEncoding.cs
similarity index 100%
rename from BepInEx/ConsoleUtil/ConsoleEncoding/ConsoleEncoding.cs
rename to BepInEx/Console/Windows/ConsoleEncoding/ConsoleEncoding.cs
diff --git a/BepInEx/ConsoleUtil/ConsoleWindow.cs b/BepInEx/Console/Windows/ConsoleWindow.cs
similarity index 84%
rename from BepInEx/ConsoleUtil/ConsoleWindow.cs
rename to BepInEx/Console/Windows/ConsoleWindow.cs
index 23f7ea4..497d6d6 100644
--- a/BepInEx/ConsoleUtil/ConsoleWindow.cs
+++ b/BepInEx/Console/Windows/ConsoleWindow.cs
@@ -7,28 +7,17 @@ using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
-using BepInEx.Configuration;
+using BepInEx;
+using Microsoft.Win32.SafeHandles;
namespace UnityInjector.ConsoleUtil
{
internal class ConsoleWindow
{
- public static readonly ConfigEntry ConfigConsoleEnabled = ConfigFile.CoreConfig.Bind(
- "Logging.Console", "Enabled",
- false,
- "Enables showing a console for log output.");
-
- public static readonly ConfigEntry ConfigConsoleShiftJis = ConfigFile.CoreConfig.Bind(
- "Logging.Console", "ShiftJisEncoding",
- false,
- "If true, console is set to the Shift-JIS encoding, otherwise UTF-8 encoding.");
-
public static bool IsAttached { get; private set; }
private static IntPtr _cOut;
private static IntPtr _oOut;
- public static TextWriter StandardOut { get; private set; }
-
public static void Attach()
{
if (IsAttached)
@@ -53,6 +42,10 @@ namespace UnityInjector.ConsoleUtil
if (!SetStdHandle(-11, _cOut))
throw new Exception("SetStdHandle() failed");
+
+ var originalOutStream = new FileStream(new SafeFileHandle(_oOut, false), FileAccess.Write);
+ ConsoleManager.StandardOutStream = new StreamWriter(originalOutStream, new UTF8Encoding(false));
+
Init();
IsAttached = true;
@@ -134,13 +127,13 @@ namespace UnityInjector.ConsoleUtil
private static void Init()
{
var stdOut = Console.OpenStandardOutput();
- StandardOut = new StreamWriter(stdOut, Encoding.Default)
+ ConsoleManager.ConsoleStream = new StreamWriter(stdOut, Encoding.Default)
{
AutoFlush = true
};
- Console.SetOut(StandardOut);
- Console.SetError(StandardOut);
+ Console.SetOut(ConsoleManager.ConsoleStream);
+ Console.SetError(ConsoleManager.ConsoleStream);
}
[DllImport("kernel32.dll", SetLastError = true)]
diff --git a/BepInEx/ConsoleUtil/Kon.cs b/BepInEx/Console/Windows/Kon.cs
similarity index 79%
rename from BepInEx/ConsoleUtil/Kon.cs
rename to BepInEx/Console/Windows/Kon.cs
index 2130348..e4f733e 100644
--- a/BepInEx/ConsoleUtil/Kon.cs
+++ b/BepInEx/Console/Windows/Kon.cs
@@ -64,27 +64,19 @@ namespace BepInEx.ConsoleUtil
succeeded = false;
if (!(conOut == INVALID_HANDLE_VALUE))
{
- try
+ CONSOLE_SCREEN_BUFFER_INFO console_SCREEN_BUFFER_INFO;
+ if (!GetConsoleScreenBufferInfo(conOut, out console_SCREEN_BUFFER_INFO))
{
- // FIXME: Windows console shouldn't be used in other OSs in the first place
- CONSOLE_SCREEN_BUFFER_INFO console_SCREEN_BUFFER_INFO;
- if (!GetConsoleScreenBufferInfo(conOut, out console_SCREEN_BUFFER_INFO))
- {
- bool consoleScreenBufferInfo = GetConsoleScreenBufferInfo(GetStdHandle(-12), out console_SCREEN_BUFFER_INFO);
- if (!consoleScreenBufferInfo)
- consoleScreenBufferInfo = GetConsoleScreenBufferInfo(GetStdHandle(-10), out console_SCREEN_BUFFER_INFO);
-
- if (!consoleScreenBufferInfo)
- if (Marshal.GetLastWin32Error() == 6 && !throwOnNoConsole)
- return default(CONSOLE_SCREEN_BUFFER_INFO);
- }
- succeeded = true;
- return console_SCREEN_BUFFER_INFO;
- }
- catch (EntryPointNotFoundException)
- {
- // Fails under unsupported OSes
+ bool consoleScreenBufferInfo = GetConsoleScreenBufferInfo(GetStdHandle(-12), out console_SCREEN_BUFFER_INFO);
+ if (!consoleScreenBufferInfo)
+ consoleScreenBufferInfo = GetConsoleScreenBufferInfo(GetStdHandle(-10), out console_SCREEN_BUFFER_INFO);
+
+ if (!consoleScreenBufferInfo)
+ if (Marshal.GetLastWin32Error() == 6 && !throwOnNoConsole)
+ return default(CONSOLE_SCREEN_BUFFER_INFO);
}
+ succeeded = true;
+ return console_SCREEN_BUFFER_INFO;
}
if (!throwOnNoConsole)
diff --git a/BepInEx/ConsoleUtil/SafeConsole.cs b/BepInEx/Console/Windows/SafeConsole.cs
similarity index 100%
rename from BepInEx/ConsoleUtil/SafeConsole.cs
rename to BepInEx/Console/Windows/SafeConsole.cs
diff --git a/BepInEx/Logging/ConsoleLogListener.cs b/BepInEx/Logging/ConsoleLogListener.cs
index 413af9c..0f4df61 100644
--- a/BepInEx/Logging/ConsoleLogListener.cs
+++ b/BepInEx/Logging/ConsoleLogListener.cs
@@ -1,6 +1,5 @@
using System;
using BepInEx.Configuration;
-using BepInEx.ConsoleUtil;
namespace BepInEx.Logging
{
@@ -16,9 +15,9 @@ namespace BepInEx.Logging
string log = $"[{eventArgs.Level,-7}:{((ILogSource)sender).SourceName,10}] {eventArgs.Data}\r\n";
- Kon.ForegroundColor = eventArgs.Level.GetConsoleColor();
+ ConsoleManager.SetConsoleColor(eventArgs.Level.GetConsoleColor());
Console.Write(log);
- Kon.ForegroundColor = ConsoleColor.Gray;
+ ConsoleManager.SetConsoleColor(ConsoleColor.Gray);
}
public void Dispose() { }