Add a minimal assembly resolver before running main preloader code

This commit is contained in:
ghorsington committed 2019-06-12 16:20:19 +03:00
1 parent 53d82b7db3
commit a8ceaa97ed
1 file changed
+45 -21
+45 -21
View File
@@ -1,37 +1,20 @@
using System;
using System.IO;
using System.Linq;
using System.Reflection;
namespace BepInEx.Preloader
{
internal static class Entrypoint
internal static class PreloaderRunner
{
/// <summary>
/// The main entrypoint of BepInEx, called from Doorstop.
/// </summary>
/// <param name="args">
/// The arguments passed in from Doorstop. First argument is the path of the currently executing
/// process.
/// </param>
public static void Main(string[] args)
public static void PreloaderMain(string[] args)
{
Paths.SetExecutablePath(args[0]);
AppDomain.CurrentDomain.AssemblyResolve += LocalResolve;
Preloader.Run();
}
/// <summary>
/// A handler for <see cref="AppDomain.AssemblyResolve" /> to perform some special handling.
/// <para>
/// It attempts to check currently loaded assemblies (ignoring the version), and then checks the BepInEx/core path,
/// BepInEx/patchers path and the BepInEx folder, all in that order.
/// </para>
/// </summary>
/// <param name="sender"></param>
/// <param name="args"></param>
/// <returns></returns>
internal static Assembly LocalResolve(object sender, ResolveEventArgs args)
private static Assembly LocalResolve(object sender, ResolveEventArgs args)
{
var assemblyName = new AssemblyName(args.Name);
@@ -49,4 +32,45 @@ namespace BepInEx.Preloader
return null;
}
}
internal static class Entrypoint
{
private static string preloaderPath;
/// <summary>
/// The main entrypoint of BepInEx, called from Doorstop.
/// </summary>
/// <param name="args">
/// The arguments passed in from Doorstop. First argument is the path of the currently executing
/// process.
/// </param>
public static void Main(string[] args)
{
// Get the path of this DLL via Doorstop env var because Assembly.Location mangles non-ASCII characters on some versions of Mono for unknown reasons
preloaderPath = Path.GetDirectoryName(Path.GetFullPath(Environment.GetEnvironmentVariable("DOORSTOP_INVOKE_DLL_PATH")));
AppDomain.CurrentDomain.AssemblyResolve += ResolveCurrentDirectory;
// We have to use reflection and a separate startup class in order to not trigger premature assembly resolving
typeof(Entrypoint).Assembly.GetType($"BepInEx.Preloader.{nameof(PreloaderRunner)}")
?.GetMethod(nameof(PreloaderRunner.PreloaderMain))
?.Invoke(null, new object[] { args });
AppDomain.CurrentDomain.AssemblyResolve -= ResolveCurrentDirectory;
}
private static Assembly ResolveCurrentDirectory(object sender, ResolveEventArgs args)
{
var name = new AssemblyName(args.Name);
try
{
return Assembly.LoadFile(Path.Combine(preloaderPath, $"{name.Name}.dll"));
}
catch (Exception)
{
return null;
}
}
}
}