Przeglądaj źródła

Add runtime fix for console logging

ghorsington 4 lat temu
rodzic
commit
a00b095eae

+ 2 - 1
BepInEx.Preloader/BepInEx.Preloader.csproj

@@ -54,9 +54,10 @@
     <Compile Include="Patching\AssemblyPatcher.cs" />
     <Compile Include="Entrypoint.cs" />
     <Compile Include="Patching\PatcherPlugin.cs" />
+    <Compile Include="RuntimeFixes\ConsoleSetOutFix.cs" />
     <Compile Include="RuntimeFixes\TraceFix.cs" />
     <Compile Include="Preloader.cs" />
-    <Compile Include="Logger\PreloaderLogWriter.cs" />
+    <Compile Include="Logger\PreloaderConsoleListener.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="RuntimeFixes\UnityPatches.cs" />
     <Compile Include="RuntimeFixes\XTermFix.cs" />

+ 3 - 0
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();
 		}

+ 26 - 0
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<LogEventArgs> LogEvents { get; } = new List<LogEventArgs>();
+
+		public void LogEvent(object sender, LogEventArgs eventArgs)
+		{
+			if ((eventArgs.Level & ConfigConsoleDisplayedLevel.Value) == 0)
+				return;
+			
+			LogEvents.Add(eventArgs);
+		}
+		
+		private static readonly ConfigEntry<LogLevel> 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() { }
+	}
+}

+ 0 - 92
BepInEx.Preloader/Logger/PreloaderLogWriter.cs

@@ -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<LogEventArgs> LogEvents { get; } = new List<LogEventArgs>();
-
-		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<LogLevel> 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<LogEventArgs> 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);
-	}
-}

+ 3 - 4
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();
 			}

+ 58 - 0
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<TextWriter> writers = new List<TextWriter>();
+
+		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));
+	}
+}

+ 1 - 1
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);
 		}
 

+ 3 - 0
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));
 		}