|
@@ -6,7 +6,6 @@ using BepInEx.Harmony;
|
|
using BepInEx.Logging;
|
|
using BepInEx.Logging;
|
|
using Harmony;
|
|
using Harmony;
|
|
using Mono.Cecil;
|
|
using Mono.Cecil;
|
|
-using UnityEngine;
|
|
|
|
|
|
|
|
namespace BepInEx.Bootstrap
|
|
namespace BepInEx.Bootstrap
|
|
{
|
|
{
|
|
@@ -153,99 +152,11 @@ namespace BepInEx.Bootstrap
|
|
assembly.Dispose();
|
|
assembly.Dispose();
|
|
}
|
|
}
|
|
|
|
|
|
- //run all finalizers
|
|
|
|
- FinalizePatching();
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /// <summary>
|
|
|
|
- /// Patches and loads an entire directory of assemblies.
|
|
|
|
- /// </summary>
|
|
|
|
- /// <param name="directory">The directory to load assemblies from.</param>
|
|
|
|
- /// <param name="patcherMethodDictionary">The dictionary of patchers and their targeted assembly filenames which they are patching.</param>
|
|
|
|
- /// <param name="initializers">List of initializers to run before any patching starts</param>
|
|
|
|
- /// <param name="finalizers">List of finalizers to run before returning</param>
|
|
|
|
- public static void PatchAll(string directory, IDictionary<AssemblyPatcherDelegate, IEnumerable<string>> patcherMethodDictionary, IEnumerable<Action> initializers = null, IEnumerable<Action> finalizers = null)
|
|
|
|
- {
|
|
|
|
- //run all initializers
|
|
|
|
- if (initializers != null)
|
|
|
|
- foreach (Action init in initializers)
|
|
|
|
- init.Invoke();
|
|
|
|
-
|
|
|
|
- //load all the requested assemblies
|
|
|
|
- Dictionary<string, AssemblyDefinition> assemblies = new Dictionary<string, AssemblyDefinition>();
|
|
|
|
-
|
|
|
|
- foreach (string assemblyPath in Directory.GetFiles(directory, "*.dll"))
|
|
|
|
- {
|
|
|
|
- var assembly = AssemblyDefinition.ReadAssembly(assemblyPath);
|
|
|
|
-
|
|
|
|
- //NOTE: this is special cased here because the dependency handling for System.dll is a bit wonky
|
|
|
|
- //System has an assembly reference to itself, and it also has a reference to Mono.Security causing a circular dependency
|
|
|
|
- //It's also generally dangerous to change system.dll since so many things rely on it,
|
|
|
|
- // and it's already loaded into the appdomain since this loader references it, so we might as well skip it
|
|
|
|
- if (assembly.Name.Name == "System"
|
|
|
|
- || assembly.Name.Name == "mscorlib") //mscorlib is already loaded into the appdomain so it can't be patched
|
|
|
|
- {
|
|
|
|
- assembly.Dispose();
|
|
|
|
- continue;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- assemblies.Add(Path.GetFileName(assemblyPath), assembly);
|
|
|
|
- PatchedAssemblyResolver.AssemblyLocations.Add(assembly.FullName, Path.GetFullPath(assemblyPath));
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- HashSet<string> patchedAssemblies = new HashSet<string>();
|
|
|
|
-
|
|
|
|
- //call the patchers on the assemblies
|
|
|
|
- foreach (var patcherMethod in patcherMethodDictionary)
|
|
|
|
- {
|
|
|
|
- foreach (string assemblyFilename in patcherMethod.Value)
|
|
|
|
- {
|
|
|
|
- if (assemblies.TryGetValue(assemblyFilename, out var assembly))
|
|
|
|
- {
|
|
|
|
- Patch(ref assembly, patcherMethod.Key);
|
|
|
|
- assemblies[assemblyFilename] = assembly;
|
|
|
|
- patchedAssemblies.Add(assemblyFilename);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // Finally, load all assemblies into memory
|
|
|
|
- foreach (var kv in assemblies)
|
|
|
|
- {
|
|
|
|
- string filename = kv.Key;
|
|
|
|
- var assembly = kv.Value;
|
|
|
|
-
|
|
|
|
- if (DumpingEnabled && patchedAssemblies.Contains(filename))
|
|
|
|
- {
|
|
|
|
- string dirPath = Path.Combine(Paths.PluginPath, "DumpedAssemblies");
|
|
|
|
-
|
|
|
|
- if (!Directory.Exists(dirPath))
|
|
|
|
- Directory.CreateDirectory(dirPath);
|
|
|
|
-
|
|
|
|
- assembly.Write(Path.Combine(dirPath, filename));
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- Load(assembly);
|
|
|
|
- assembly.Dispose();
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // Patch Assembly.Location and Assembly.CodeBase only if the assemblies were loaded from memory
|
|
|
|
|
|
+ // Apply assembly location resolver patch
|
|
PatchedAssemblyResolver.ApplyPatch();
|
|
PatchedAssemblyResolver.ApplyPatch();
|
|
|
|
|
|
//run all finalizers
|
|
//run all finalizers
|
|
- if (finalizers != null)
|
|
|
|
- foreach (Action finalizer in finalizers)
|
|
|
|
- finalizer.Invoke();
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /// <summary>
|
|
|
|
- /// Patches an individual assembly, without loading it.
|
|
|
|
- /// </summary>
|
|
|
|
- /// <param name="assembly">The assembly definition to apply the patch to.</param>
|
|
|
|
- /// <param name="patcherMethod">The patcher to use to patch the assembly definition.</param>
|
|
|
|
- public static void Patch(ref AssemblyDefinition assembly, AssemblyPatcherDelegate patcherMethod)
|
|
|
|
- {
|
|
|
|
- patcherMethod.Invoke(ref assembly);
|
|
|
|
|
|
+ FinalizePatching();
|
|
}
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// <summary>
|