Skip to content
Permalink
Browse files

Fix assembly load warning not always working in preloader

  • Loading branch information
denikson committed Nov 17, 2019
1 parent 7c4afe1 commit d527fd04b69b7789b5a6500f65686be4e6505534
Showing with 23 additions and 3 deletions.
  1. +23 −3 BepInEx.Preloader/Patching/AssemblyPatcher.cs
@@ -4,6 +4,7 @@
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
@@ -217,20 +218,39 @@ public static void PatchAndLoad(string directory)

// Then, perform the actual patching
var patchedAssemblies = new HashSet<string>();
var resolvedAssemblies = new Dictionary<string, string>();
foreach (var assemblyPatcher in PatcherPlugins)
foreach (string targetDll in assemblyPatcher.TargetDLLs())
if (assemblies.TryGetValue(targetDll, out var assembly))
{
if (AppDomain.CurrentDomain.GetAssemblies().Any(x => x.GetName().Name == assembly.Name.Name))
Logger.LogWarning($"Trying to patch an already loaded assembly [{assembly.Name.Name}] with [{assemblyPatcher.TypeName}]");

Logger.LogInfo($"Patching [{assembly.Name.Name}] with [{assemblyPatcher.TypeName}]");

assemblyPatcher.Patcher?.Invoke(ref assembly);
assemblies[targetDll] = assembly;
patchedAssemblies.Add(targetDll);

foreach (var resolvedAss in AppDomain.CurrentDomain.GetAssemblies())
{
var name = resolvedAss.GetName().Name;
// Report only the first type that caused the assembly to load, because any subsequent ones can be false positives
if (!resolvedAssemblies.ContainsKey(name))
resolvedAssemblies[name] = assemblyPatcher.TypeName;
}
}

// Check if any patched assemblies have been already resolved by the CLR
// If there are any, they cannot be loaded by the preloader
var patchedAssemblyNames = new HashSet<string>(assemblies.Where(kv => patchedAssemblies.Contains(kv.Key)).Select(kv => kv.Value.Name.Name));
var earlyLoadAssemblies = resolvedAssemblies.Where(kv => patchedAssemblyNames.Contains(kv.Key)).ToList();

if (earlyLoadAssemblies.Count != 0)
{
Logger.LogWarning(new StringBuilder()
.AppendLine("The following assemblies have been loaded too early and will not be patched by preloader:")
.AppendLine(string.Join(Environment.NewLine, earlyLoadAssemblies.Select(kv => $"* [{kv.Key}] (first loaded by [{kv.Value}])").ToArray()))
.AppendLine("Expect unexpected behavior and issues with plugins and patchers not being loaded.")
.ToString());
}

// Finally, load patched assemblies into memory
if (ConfigDumpAssemblies.Value || ConfigLoadDumpedAssemblies.Value)

0 comments on commit d527fd0

Please sign in to comment.
You can’t perform that action at this time.