mirror of
https://github.com/BepInEx/BepInEx.git
synced 2026-10-20 01:46:13 +00:00
74 lines
2.1 KiB
C#
74 lines
2.1 KiB
C#
using System;
|
|
using System.Diagnostics;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using Harmony;
|
|
|
|
namespace BepInEx.Preloader.RuntimeFixes
|
|
{
|
|
/// <summary>
|
|
/// This exists because the Mono implementation of <see cref="Trace"/> is/was broken, and would call Write directly instead of calling TraceEvent. This class fixes that with a <see cref="Harmony"/> hook.
|
|
/// </summary>
|
|
internal static class TraceFix
|
|
{
|
|
private static Type TraceImplType;
|
|
|
|
private static object ListenersSyncRoot;
|
|
private static TraceListenerCollection Listeners;
|
|
private static PropertyInfo prop_AutoFlush;
|
|
|
|
private static bool AutoFlush => (bool)prop_AutoFlush.GetValue(null, null);
|
|
|
|
|
|
public static void ApplyFix()
|
|
{
|
|
TraceImplType = AppDomain.CurrentDomain.GetAssemblies()
|
|
.First(x => x.GetName().Name == "System")
|
|
.GetTypes()
|
|
.First(x => x.Name == "TraceImpl");
|
|
|
|
|
|
ListenersSyncRoot = AccessTools.Property(TraceImplType, "ListenersSyncRoot").GetValue(null, null);
|
|
|
|
Listeners = (TraceListenerCollection)AccessTools.Property(TraceImplType, "Listeners").GetValue(null, null);
|
|
|
|
prop_AutoFlush = AccessTools.Property(TraceImplType, "AutoFlush");
|
|
|
|
|
|
HarmonyInstance instance = HarmonyInstance.Create("com.bepis.bepinex.tracefix");
|
|
|
|
instance.Patch(
|
|
typeof(Trace).GetMethod("DoTrace", BindingFlags.Static | BindingFlags.NonPublic),
|
|
prefix: new HarmonyMethod(typeof(TraceFix).GetMethod(nameof(DoTraceReplacement), BindingFlags.Static | BindingFlags.NonPublic)));
|
|
}
|
|
|
|
|
|
private static bool DoTraceReplacement(string kind, Assembly report, string message)
|
|
{
|
|
string arg = string.Empty;
|
|
try
|
|
{
|
|
arg = report.GetName().Name;
|
|
}
|
|
catch (MethodAccessException) { }
|
|
|
|
TraceEventType type = (TraceEventType)Enum.Parse(typeof(TraceEventType), kind);
|
|
|
|
lock (ListenersSyncRoot)
|
|
{
|
|
foreach (object obj in Listeners)
|
|
{
|
|
TraceListener traceListener = (TraceListener)obj;
|
|
traceListener.TraceEvent(new TraceEventCache(), arg, type, 0, message);
|
|
|
|
if (AutoFlush)
|
|
{
|
|
traceListener.Flush();
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
}
|
|
} |