mirror of
https://github.com/BepInEx/BepInEx.git
synced 2026-10-20 01:46:13 +00:00
Simplify ConsoleSetOut fix; redirect console messages to logging system
This commit is contained in:
1 parent
dc6c76b59f
commit
f2b7b9993e
5 files changed
+30
-76
No files matched your search
@@ -1,29 +1,20 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using BepInEx.Logging;
|
||||
using HarmonyLib;
|
||||
|
||||
namespace BepInEx.Preloader.RuntimeFixes
|
||||
{
|
||||
/*
|
||||
* By default, setting Console.Out removes the previous listener
|
||||
* This can be a problem in Unity because it installs its own TextWriter while BepInEx needs to install it
|
||||
* one too for the console. This runtime fix collects all Console.Out setters and aggregates them into a single
|
||||
* text writer.
|
||||
*
|
||||
* This allows to both fix the old problem with log overwriting and problem with writing stdout when console is
|
||||
* enabled.
|
||||
*/
|
||||
internal static class ConsoleSetOutFix
|
||||
{
|
||||
private static AggregatedTextWriter aggregatedTextWriter;
|
||||
private static LoggedTextWriter loggedTextWriter;
|
||||
internal static ManualLogSource ConsoleLogSource = Logger.CreateLogSource("Console");
|
||||
|
||||
public static void Apply()
|
||||
{
|
||||
aggregatedTextWriter = new AggregatedTextWriter(Console.Out);
|
||||
Console.SetOut(aggregatedTextWriter);
|
||||
loggedTextWriter = new LoggedTextWriter { Parent = Console.Out };
|
||||
Console.SetOut(loggedTextWriter);
|
||||
HarmonyLib.Harmony.CreateAndPatchAll(typeof(ConsoleSetOutFix));
|
||||
}
|
||||
|
||||
@@ -31,39 +22,29 @@ namespace BepInEx.Preloader.RuntimeFixes
|
||||
[HarmonyPrefix]
|
||||
private static bool OnSetOut(TextWriter newOut)
|
||||
{
|
||||
if (newOut == TextWriter.Null)
|
||||
return false;
|
||||
aggregatedTextWriter.Add(newOut);
|
||||
loggedTextWriter.Parent = newOut;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
internal class AggregatedTextWriter : TextWriter
|
||||
internal class LoggedTextWriter : TextWriter
|
||||
{
|
||||
public override Encoding Encoding { get; } = Encoding.UTF8;
|
||||
|
||||
private List<TextWriter> writers = new List<TextWriter>();
|
||||
public TextWriter Parent { get; set; }
|
||||
|
||||
public AggregatedTextWriter(params TextWriter[] initialWriters)
|
||||
public override void Flush() => Parent.Flush();
|
||||
|
||||
public override void Write(string value)
|
||||
{
|
||||
writers.AddRange(initialWriters.Where(w => w != null));
|
||||
ConsoleSetOutFix.ConsoleLogSource.LogInfo(value);
|
||||
Parent.Write(value);
|
||||
}
|
||||
|
||||
public void Add(TextWriter tw)
|
||||
public override void WriteLine(string value)
|
||||
{
|
||||
if (writers.Any(t => t == tw))
|
||||
return;
|
||||
writers.Add(tw);
|
||||
ConsoleSetOutFix.ConsoleLogSource.LogInfo(value);
|
||||
Parent.WriteLine(value);
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
@@ -86,9 +86,7 @@ namespace BepInEx.Bootstrap
|
||||
// Add Unity log source only after replaying to prevent duplication in console
|
||||
if (ConfigUnityLogging.Value)
|
||||
Logger.Sources.Add(new UnityLogSource());
|
||||
// Write to Unity logs directly only if console is not present (or user explicitly wants to)
|
||||
if (ConfigWriteToUnityLog.Value || !ConsoleManager.ConsoleActive)
|
||||
Logger.Listeners.Add(new UnityLogListener());
|
||||
Logger.Listeners.Add(new UnityLogListener());
|
||||
|
||||
if (Utility.CurrentOs == Platform.Linux)
|
||||
{
|
||||
@@ -415,14 +413,6 @@ namespace BepInEx.Bootstrap
|
||||
true,
|
||||
"Enables showing unity log messages in the BepInEx logging system.");
|
||||
|
||||
private static readonly ConfigEntry<bool> ConfigWriteToUnityLog = ConfigFile.CoreConfig.Bind(
|
||||
"Logging", "WriteToUnityLog",
|
||||
false,
|
||||
new StringBuilder()
|
||||
.AppendLine("Enables writing log messages to Unity's log system")
|
||||
.AppendLine("NOTE: By default, Unity already writes BepInEx console output to Unity logs")
|
||||
.Append("Use this setting only if no BepInEx log messages are present in Unity's output_log").ToString());
|
||||
|
||||
private static readonly ConfigEntry<bool> ConfigDiskWriteUnityLog = ConfigFile.CoreConfig.Bind(
|
||||
"Logging.Disk", "WriteUnityLog",
|
||||
false,
|
||||
|
||||
@@ -56,7 +56,6 @@ namespace BepInEx
|
||||
throw new InvalidOperationException("Driver has not been initialized");
|
||||
}
|
||||
|
||||
|
||||
public static void CreateConsole()
|
||||
{
|
||||
if (ConsoleActive)
|
||||
@@ -70,7 +69,6 @@ namespace BepInEx
|
||||
var codepage = ConfigConsoleShiftJis.Value ? SHIFT_JIS_CP: (uint)Encoding.UTF8.CodePage;
|
||||
|
||||
Driver.CreateConsole(codepage);
|
||||
SetConsoleStreams();
|
||||
}
|
||||
|
||||
public static void DetachConsole()
|
||||
@@ -81,7 +79,6 @@ namespace BepInEx
|
||||
DriverCheck();
|
||||
|
||||
Driver.DetachConsole();
|
||||
SetConsoleStreams();
|
||||
}
|
||||
|
||||
public static void SetConsoleTitle(string title)
|
||||
@@ -98,20 +95,6 @@ namespace BepInEx
|
||||
Driver.SetConsoleColor(color);
|
||||
}
|
||||
|
||||
internal static void SetConsoleStreams()
|
||||
{
|
||||
if (ConsoleActive)
|
||||
{
|
||||
Console.SetOut(ConsoleStream);
|
||||
Console.SetError(ConsoleStream);
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.SetOut(TextWriter.Null);
|
||||
Console.SetError(TextWriter.Null);
|
||||
}
|
||||
}
|
||||
|
||||
public static readonly ConfigEntry<bool> ConfigConsoleEnabled = ConfigFile.CoreConfig.Bind(
|
||||
"Logging.Console", "Enabled",
|
||||
false,
|
||||
|
||||
@@ -14,20 +14,10 @@ namespace BepInEx.Logging
|
||||
return;
|
||||
|
||||
ConsoleManager.SetConsoleColor(eventArgs.Level.GetConsoleColor());
|
||||
Log(eventArgs);
|
||||
ConsoleManager.ConsoleStream?.Write(eventArgs.ToStringLine());
|
||||
ConsoleManager.SetConsoleColor(ConsoleColor.Gray);
|
||||
}
|
||||
|
||||
private void Log(LogEventArgs eventArgs)
|
||||
{
|
||||
// Special case: if message comes from Unity log, it's already logged by Unity, in which case
|
||||
// we replay it only in the visible console
|
||||
if (eventArgs.Source is UnityLogSource)
|
||||
ConsoleManager.ConsoleStream?.Write(eventArgs.ToStringLine());
|
||||
else
|
||||
Console.Write(eventArgs.ToStringLine());
|
||||
}
|
||||
|
||||
public void Dispose() { }
|
||||
|
||||
private static readonly ConfigEntry<LogLevel> ConfigConsoleDisplayedLevel = ConfigFile.CoreConfig.Bind(
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using BepInEx.Configuration;
|
||||
|
||||
namespace BepInEx.Logging
|
||||
{
|
||||
@@ -36,11 +38,19 @@ namespace BepInEx.Logging
|
||||
{
|
||||
if (eventArgs.Source is UnityLogSource)
|
||||
return;
|
||||
|
||||
WriteStringToUnityLog?.Invoke(eventArgs.ToStringLine());
|
||||
|
||||
// Special case: don't write console twice since Unity can already do that
|
||||
if (LogConsoleToUnity.Value || eventArgs.Source.SourceName != "Console")
|
||||
WriteStringToUnityLog?.Invoke(eventArgs.ToStringLine());
|
||||
}
|
||||
|
||||
public void Dispose() { }
|
||||
|
||||
private ConfigEntry<bool> LogConsoleToUnity = ConfigFile.CoreConfig.Bind("Logging",
|
||||
"LogConsoleToUnityLog", false,
|
||||
new StringBuilder()
|
||||
.AppendLine("If enabled, writes Standard Output messages to Unity log")
|
||||
.AppendLine("NOTE: By default, Unity does so automatically. Only use this option if no console messages are visible in Unity log").ToString());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user