mirror of
https://github.com/BepInEx/BepInEx.git
synced 2026-10-20 01:46:13 +00:00
75 lines
2.6 KiB
C#
75 lines
2.6 KiB
C#
using System;
|
|
using System.Diagnostics;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using HarmonyLib;
|
|
|
|
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.
|
|
/// </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()
|
|
.FirstOrDefault(x => x.Name == "TraceImpl");
|
|
// assembly that has already fixed this
|
|
if (TraceImplType == null) return;
|
|
|
|
ListenersSyncRoot = AccessTools.Property(TraceImplType, "ListenersSyncRoot").GetValue(null, null);
|
|
|
|
Listeners = (TraceListenerCollection) AccessTools.Property(TraceImplType, "Listeners").GetValue(null, null);
|
|
|
|
prop_AutoFlush = AccessTools.Property(TraceImplType, "AutoFlush");
|
|
|
|
|
|
var instance = new Harmony("com.bepis.bepinex.tracefix");
|
|
|
|
instance.Patch(
|
|
typeof(Trace).GetMethod("DoTrace", BindingFlags.Static | BindingFlags.NonPublic),
|
|
new HarmonyMethod(typeof(TraceFix).GetMethod(nameof(DoTraceReplacement),
|
|
BindingFlags.Static | BindingFlags.NonPublic)));
|
|
}
|
|
|
|
|
|
private static bool DoTraceReplacement(string kind, Assembly report, string message)
|
|
{
|
|
var arg = string.Empty;
|
|
try
|
|
{
|
|
arg = report.GetName().Name;
|
|
}
|
|
catch (MethodAccessException) { }
|
|
|
|
var type = (TraceEventType) Enum.Parse(typeof(TraceEventType), kind);
|
|
|
|
lock (ListenersSyncRoot)
|
|
{
|
|
foreach (var obj in Listeners)
|
|
{
|
|
var traceListener = (TraceListener) obj;
|
|
traceListener.TraceEvent(new TraceEventCache(), arg, type, 0, message);
|
|
|
|
if (AutoFlush) traceListener.Flush();
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
}
|
|
}
|