Automatically load all interop assemblies before loading plugins (#777)

Assemblies are often loaded on the il2cpp side but not on the mono side, causing confusion when using reflection.
This will load all interop assemblies right before plugins are loaded, which should mostly avoid these issues at a low time cost of around 40ms.
This commit is contained in:
ManlyMarco authored and GitHub committed 2024-09-08 15:45:19 +02:00
1 parent 2a61b61497
commit cbd70eb2f0
2 files changed
+40

No files matched your search

@@ -97,6 +97,8 @@ public class IL2CPPChainloader : BaseChainloader<BasePlugin>
unhook = true;
Il2CppInteropManager.PreloadInteropAssemblies();
Instance.Execute();
}
catch (Exception ex)
@@ -8,6 +8,8 @@ using System.Reflection;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using BepInEx.Configuration;
using BepInEx.Logging;
using BepInEx.Unity.Common;
@@ -88,6 +90,14 @@ internal static partial class Il2CppInteropManager
.AppendLine("{BepInEx} - Path to the BepInEx folder.")
.AppendLine("{ProcessName} - Name of the current process")
.ToString());
private static readonly ConfigEntry<bool> PreloadIL2CPPInteropAssemblies = ConfigFile.CoreConfig.Bind(
"IL2CPP", "PreloadIL2CPPInteropAssemblies",
true,
new StringBuilder()
.AppendLine("Automatically load all interop assemblies right before loading plugins.")
.AppendLine("Some plugins may not work properly without this, but it may cause issues in some games.")
.ToString());
private static readonly ManualLogSource Logger = BepInEx.Logging.Logger.CreateLogSource("InteropManager");
@@ -357,4 +367,32 @@ internal static partial class Il2CppInteropManager
sourceAssemblies.Do(x => x.Dispose());
}
internal static void PreloadInteropAssemblies()
{
if (!PreloadIL2CPPInteropAssemblies.Value)
return;
var sw = Stopwatch.StartNew();
var files = Directory.EnumerateFiles(IL2CPPInteropAssemblyPath);
var loaded = 0;
Parallel.ForEach(files, file =>
{
if (!file.EndsWith(".dll", StringComparison.OrdinalIgnoreCase)) return;
if (file.Equals("netstandard.dll", StringComparison.OrdinalIgnoreCase)) return;
if (file.Equals("Il2Cppnetstandard.dll", StringComparison.OrdinalIgnoreCase)) return;
try
{
Assembly.LoadFrom(file);
Interlocked.Increment(ref loaded);
}
catch (Exception e)
{
Logger.LogWarning($"Failed to preload {file} - {e}");
}
});
Logger.LogDebug($"Preloaded {loaded} interop assemblies in {sw.ElapsedMilliseconds}ms");
}
}