diff --git a/BepInEx.Preloader/BepInEx.Preloader.csproj b/BepInEx.Preloader/BepInEx.Preloader.csproj
index 94ee13f..dd5fdd8 100644
--- a/BepInEx.Preloader/BepInEx.Preloader.csproj
+++ b/BepInEx.Preloader/BepInEx.Preloader.csproj
@@ -54,9 +54,10 @@
+
-
+
diff --git a/BepInEx.Preloader/Entrypoint.cs b/BepInEx.Preloader/Entrypoint.cs
index bf7014a..6c9abc0 100644
--- a/BepInEx.Preloader/Entrypoint.cs
+++ b/BepInEx.Preloader/Entrypoint.cs
@@ -21,7 +21,10 @@ namespace BepInEx.Preloader
private static void PreloaderMain()
{
if (Preloader.ConfigApplyRuntimePatches.Value)
+ {
XTermFix.Apply();
+ ConsoleSetOutFix.Apply();
+ }
Preloader.Run();
}
diff --git a/BepInEx.Preloader/Logger/PreloaderConsoleListener.cs b/BepInEx.Preloader/Logger/PreloaderConsoleListener.cs
new file mode 100644
index 0000000..ce3b680
--- /dev/null
+++ b/BepInEx.Preloader/Logger/PreloaderConsoleListener.cs
@@ -0,0 +1,26 @@
+using System.Collections.Generic;
+using BepInEx.Configuration;
+using BepInEx.Logging;
+
+namespace BepInEx.Preloader
+{
+ public class PreloaderConsoleListener : ILogListener
+ {
+ public static List LogEvents { get; } = new List();
+
+ public void LogEvent(object sender, LogEventArgs eventArgs)
+ {
+ if ((eventArgs.Level & ConfigConsoleDisplayedLevel.Value) == 0)
+ return;
+
+ LogEvents.Add(eventArgs);
+ }
+
+ private static readonly ConfigEntry ConfigConsoleDisplayedLevel = ConfigFile.CoreConfig.Bind(
+ "Logging.Console","LogLevels",
+ LogLevel.Fatal | LogLevel.Error | LogLevel.Message | LogLevel.Info,
+ "Which log levels to show in the console output.");
+
+ public void Dispose() { }
+ }
+}
\ No newline at end of file
diff --git a/BepInEx.Preloader/Logger/PreloaderLogWriter.cs b/BepInEx.Preloader/Logger/PreloaderLogWriter.cs
deleted file mode 100644
index 267b907..0000000
--- a/BepInEx.Preloader/Logger/PreloaderLogWriter.cs
+++ /dev/null
@@ -1,92 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Text;
-using BepInEx.Configuration;
-using BepInEx.Logging;
-
-namespace BepInEx.Preloader
-{
- public class PreloaderConsoleListener : ILogListener
- {
- public static List LogEvents { get; } = new List();
-
- public static TextWriter StandardOut { get; set; }
- protected PreloaderConsoleSource LoggerSource { get; set; }
-
-
- public PreloaderConsoleListener(bool redirectConsole)
- {
- StandardOut = Console.Out;
-
- if (redirectConsole)
- {
- LoggerSource = new PreloaderConsoleSource();
-
- Logger.Sources.Add(LoggerSource);
- Console.SetOut(LoggerSource);
- }
- }
-
- public void LogEvent(object sender, LogEventArgs eventArgs)
- {
- if ((eventArgs.Level & ConfigConsoleDisplayedLevel.Value) == 0)
- return;
-
- LogEvents.Add(eventArgs);
-
- ConsoleManager.SetConsoleColor(eventArgs.Level.GetConsoleColor());
- ConsoleDirectWrite(eventArgs.ToStringLine());
- ConsoleManager.SetConsoleColor(ConsoleColor.Gray);
- }
-
- public void ConsoleDirectWrite(string value)
- {
- StandardOut.Write(value);
- }
-
- public void ConsoleDirectWriteLine(string value)
- {
- StandardOut.WriteLine(value);
- }
-
- public void Dispose()
- {
- if (LoggerSource != null)
- {
- Console.SetOut(StandardOut);
- Logger.Sources.Remove(LoggerSource);
- LoggerSource.Dispose();
- LoggerSource = null;
- }
- }
-
- private static readonly ConfigEntry ConfigConsoleDisplayedLevel = ConfigFile.CoreConfig.Bind(
- "Logging.Console","LogLevels",
- LogLevel.Fatal | LogLevel.Error | LogLevel.Message | LogLevel.Info,
- "Which log levels to show in the console output.");
- }
-
- public class PreloaderConsoleSource : TextWriter, ILogSource
- {
- public override Encoding Encoding { get; } = Console.OutputEncoding;
-
- public string SourceName { get; } = "BepInEx Preloader";
-
- public event EventHandler LogEvent;
-
- public override void Write(object value)
- => LogEvent?.Invoke(this, new LogEventArgs(value, LogLevel.Info, this));
-
- public override void Write(string value)
- => Write((object)value);
-
- public override void WriteLine() { }
-
- public override void WriteLine(object value)
- => Write(value);
-
- public override void WriteLine(string value)
- => Write(value);
- }
-}
\ No newline at end of file
diff --git a/BepInEx.Preloader/Preloader.cs b/BepInEx.Preloader/Preloader.cs
index 8533424..3fab8f4 100644
--- a/BepInEx.Preloader/Preloader.cs
+++ b/BepInEx.Preloader/Preloader.cs
@@ -42,8 +42,9 @@ namespace BepInEx.Preloader
Logger.InitializeInternalLoggers();
Logger.Sources.Add(TraceLogSource.CreateSource());
-
- PreloaderLog = new PreloaderConsoleListener(ConfigPreloaderCOutLogging.Value);
+
+ Logger.Listeners.Add(new ConsoleLogListener());
+ PreloaderLog = new PreloaderConsoleListener();
Logger.Listeners.Add(PreloaderLog);
string consoleTile = $"BepInEx {typeof(Paths).Assembly.GetName().Version} - {Path.GetFileNameWithoutExtension(Process.GetCurrentProcess().ProcessName)}";
@@ -85,11 +86,9 @@ namespace BepInEx.Preloader
AssemblyPatcher.PatchAndLoad(Paths.ManagedPath);
AssemblyPatcher.DisposePatchers();
-
Logger.LogMessage("Preloader finished");
Logger.Listeners.Remove(PreloaderLog);
- Logger.Listeners.Add(new ConsoleLogListener());
PreloaderLog.Dispose();
}
diff --git a/BepInEx.Preloader/RuntimeFixes/ConsoleSetOutFix.cs b/BepInEx.Preloader/RuntimeFixes/ConsoleSetOutFix.cs
new file mode 100644
index 0000000..050d59a
--- /dev/null
+++ b/BepInEx.Preloader/RuntimeFixes/ConsoleSetOutFix.cs
@@ -0,0 +1,58 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using HarmonyLib;
+
+namespace BepInEx.Preloader.RuntimeFixes
+{
+ internal static class ConsoleSetOutFix
+ {
+ private static AggregatedTextWriter aggregatedTextWriter;
+
+ public static void Apply()
+ {
+ aggregatedTextWriter = new AggregatedTextWriter(Console.Out);
+ Console.SetOut(aggregatedTextWriter);
+ HarmonyLib.Harmony.CreateAndPatchAll(typeof(ConsoleSetOutFix));
+ }
+
+ [HarmonyPatch(typeof(Console), nameof(Console.SetOut))]
+ [HarmonyPrefix]
+ private static bool OnSetOut(TextWriter newOut)
+ {
+ aggregatedTextWriter.Add(newOut);
+ return false;
+ }
+ }
+
+ internal class AggregatedTextWriter : TextWriter
+ {
+ public override Encoding Encoding { get; } = Encoding.UTF8;
+
+ private List writers = new List();
+
+ public AggregatedTextWriter(params TextWriter[] initialWriters)
+ {
+ writers.AddRange(initialWriters.Where(w => w != null));
+ }
+
+ public void Add(TextWriter tw)
+ {
+ if (writers.Any(t => t == tw))
+ return;
+ writers.Add(tw);
+ }
+
+ public override void Flush() => writers.ForEach(w => w.Flush());
+
+ public override void Write(object value) => writers.ForEach(w => w.Write(value));
+ public override void Write(string value) => writers.ForEach(w => w.Write(value));
+ public override void Write(char value) => writers.ForEach(w => w.Write(value));
+
+ public override void WriteLine(object value) => writers.ForEach(w => w.WriteLine(value));
+ public override void WriteLine(string value) => writers.ForEach(w => w.WriteLine(value));
+ public override void WriteLine(char value) => writers.ForEach(w => w.WriteLine(value));
+ }
+}
\ No newline at end of file
diff --git a/BepInEx/Logging/ConsoleLogListener.cs b/BepInEx/Logging/ConsoleLogListener.cs
index e8be39a..d0f67bb 100644
--- a/BepInEx/Logging/ConsoleLogListener.cs
+++ b/BepInEx/Logging/ConsoleLogListener.cs
@@ -13,7 +13,7 @@ namespace BepInEx.Logging
if ((eventArgs.Level & ConfigConsoleDisplayedLevel.Value) == 0)
return;
ConsoleManager.SetConsoleColor(eventArgs.Level.GetConsoleColor());
- ConsoleManager.ConsoleStream?.Write(eventArgs.ToStringLine());
+ Console.Write(eventArgs.ToStringLine());
ConsoleManager.SetConsoleColor(ConsoleColor.Gray);
}
diff --git a/BepInEx/Logging/UnityLogSource.cs b/BepInEx/Logging/UnityLogSource.cs
index fe04cf3..359ec72 100644
--- a/BepInEx/Logging/UnityLogSource.cs
+++ b/BepInEx/Logging/UnityLogSource.cs
@@ -1,4 +1,5 @@
using System;
+using System.IO;
using System.Reflection;
using UnityEngine;
@@ -78,6 +79,8 @@ namespace BepInEx.Logging
if (type == LogType.Exception)
message += $"\nStack trace:\n{stackTrace}";
+
+ File.WriteAllText("unity.log", $"{message}\n");
InternalUnityLogMessage?.Invoke(null, new LogEventArgs(message, logLevel, null));
}