123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136 |
- using System;
- using System.Diagnostics;
- using System.IO;
- using System.Linq;
- using System.Reflection;
- using BepInEx.Bootstrap;
- using BepInEx.Configuration;
- using BepInEx.Logging;
- using BepInEx.NetLauncher.RuntimeFixes;
- using BepInEx.Preloader.Core;
- using BepInEx.Preloader.Core.RuntimeFixes;
- using MonoMod.RuntimeDetour;
- namespace BepInEx.NetLauncher
- {
- public static class NetPreloader
- {
- private static readonly ManualLogSource Log = PreloaderLogger.Log;
- public static void Start(string[] args)
- {
- if (ConfigEntrypointExecutable.Value == null)
- {
- Log.LogFatal($"Entry executable was not set. Please set this in your config before launching the application");
- Program.ReadExit();
- return;
- }
- string executablePath = Path.GetFullPath(ConfigEntrypointExecutable.Value);
- if (!File.Exists(executablePath))
- {
- Log.LogFatal($"Unable to locate executable: {ConfigEntrypointExecutable.Value}");
- Program.ReadExit();
- return;
- }
- Paths.SetExecutablePath(executablePath);
- Program.ResolveDirectories.Add(Paths.GameRootPath);
- TypeLoader.SearchDirectories.Add(Paths.GameRootPath);
- bool bridgeInitialized = Utility.TryDo(() =>
- {
- if (ConfigShimHarmony.Value)
- HarmonyDetourBridge.Init();
- }, out var harmonyBridgeException);
- Logger.Sources.Add(TraceLogSource.CreateSource());
- HarmonyFixes.Apply();
- string consoleTile = $"BepInEx {typeof(Paths).Assembly.GetName().Version} - {Process.GetCurrentProcess().ProcessName}";
- Log.LogMessage(consoleTile);
- if (ConsoleManager.ConsoleActive)
- ConsoleManager.SetConsoleTitle(consoleTile);
- //See BuildInfoAttribute for more information about this section.
- object[] attributes = typeof(BuildInfoAttribute).Assembly.GetCustomAttributes(typeof(BuildInfoAttribute), false);
- if (attributes.Length > 0)
- {
- var attribute = (BuildInfoAttribute)attributes[0];
- Log.LogMessage(attribute.Info);
- }
- Log.LogInfo($"CLR runtime version: {Environment.Version}");
- if (harmonyBridgeException != null)
- Log.LogWarning($"Failed to enable fix for Harmony for .NET Standard API. Error message: {harmonyBridgeException.Message}");
- Log.LogMessage("Preloader started");
- Assembly entrypointAssembly;
- using (var assemblyPatcher = new AssemblyPatcher())
- {
- assemblyPatcher.AddPatchersFromDirectory(Paths.PatcherPluginPath);
- Log.LogInfo($"{assemblyPatcher.PatcherPlugins.Count} patcher plugin(s) loaded");
- assemblyPatcher.LoadAssemblyDirectory(Paths.GameRootPath, "dll", "exe");
- Log.LogInfo($"{assemblyPatcher.AssembliesToPatch.Count} assemblies discovered");
- assemblyPatcher.PatchAndLoad();
- var assemblyName = AssemblyName.GetAssemblyName(executablePath);
- entrypointAssembly = assemblyPatcher.LoadedAssemblies.Values.FirstOrDefault(x => x.FullName == assemblyName.FullName);
- if (entrypointAssembly != null)
- {
- Log.LogDebug("Found patched entrypoint assembly! Using it");
- }
- else
- {
- Log.LogDebug("Using entrypoint assembly from disk");
- entrypointAssembly = Assembly.LoadFrom(executablePath);
- }
- }
- Log.LogMessage("Preloader finished");
- var chainloader = new NetChainloader();
- chainloader.Initialize();
- chainloader.Execute();
- AssemblyFix.Execute(entrypointAssembly);
- entrypointAssembly.EntryPoint.Invoke(null, new [] { args });
- }
- #region Config
- private static readonly ConfigEntry<string> ConfigEntrypointExecutable = ConfigFile.CoreConfig.Bind<string>(
- "Preloader.Entrypoint", "Assembly",
- null,
- "The local filename of the .NET executable to target.");
- private static readonly ConfigEntry<bool> ConfigShimHarmony = ConfigFile.CoreConfig.Bind(
- "Preloader", "ShimHarmonySupport",
- !Utility.CLRSupportsDynamicAssemblies,
- "If enabled, basic Harmony functionality is patched to use MonoMod's RuntimeDetour instead.\nTry using this if Harmony does not work in a game.");
- private static readonly ConfigEntry<bool> ConfigPreloaderCOutLogging = ConfigFile.CoreConfig.Bind(
- "Logging", "PreloaderConsoleOutRedirection",
- true,
- "Redirects text from Console.Out during preloader patch loading to the BepInEx logging system.");
- #endregion
- }
- }
|