public static void Run() { try { ConsoleManager.Initialize(false); PreloaderLog = new PreloaderConsoleListener(); Logger.Listeners.Add(PreloaderLog); if (ConsoleManager.ConfigConsoleEnabled.Value) { ConsoleManager.CreateConsole(); Logger.Listeners.Add(new ConsoleLogListener()); } ChainloaderLogHelper.PrintLogInfo(Log); Log.LogInfo($"Running under Unity v{FileVersionInfo.GetVersionInfo(Paths.ExecutablePath).FileVersion}"); Log.LogDebug($"Game executable path: {Paths.ExecutablePath}"); Log.LogDebug($"Unhollowed assembly directory: {IL2CPPUnhollowedPath}"); Log.LogDebug($"BepInEx root path: {Paths.BepInExRootPath}"); UnhollowerLog = Logger.CreateLogSource("Unhollower"); UnhollowerBaseLib.LogSupport.InfoHandler += UnhollowerLog.LogInfo; UnhollowerBaseLib.LogSupport.WarningHandler += UnhollowerLog.LogWarning; UnhollowerBaseLib.LogSupport.TraceHandler += UnhollowerLog.LogDebug; UnhollowerBaseLib.LogSupport.ErrorHandler += UnhollowerLog.LogError; if (ProxyAssemblyGenerator.CheckIfGenerationRequired()) { ProxyAssemblyGenerator.GenerateAssemblies(); } using (var assemblyPatcher = new AssemblyPatcher()) { assemblyPatcher.AddPatchersFromDirectory(Paths.PatcherPluginPath); Log.LogInfo($"{assemblyPatcher.PatcherPlugins.Count} patcher plugin{(assemblyPatcher.PatcherPlugins.Count == 1 ? "" : "s")} loaded"); assemblyPatcher.LoadAssemblyDirectory(IL2CPPUnhollowedPath); Log.LogInfo($"{assemblyPatcher.PatcherPlugins.Count} assemblies discovered"); assemblyPatcher.PatchAndLoad(); } Logger.Listeners.Remove(PreloaderLog); Chainloader = new IL2CPPChainloader(); Chainloader.Initialize(); } catch (Exception ex) { Log.LogFatal(ex); throw; } }
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); Logger.Sources.Add(TraceLogSource.CreateSource()); ChainloaderLogHelper.PrintLogInfo(Log); Log.LogInfo($"CLR runtime version: {Environment.Version}"); 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 }); }
public static void Run(string managedDirectory) { try { InitializeHarmony(); ConsoleManager.Initialize(false); AllocateConsole(); if (managedDirectory != null) { ManagedPath = managedDirectory; } Utility.TryDo(() => { if (ConfigApplyRuntimePatches.Value) { UnityPatches.Apply(); } }, out var runtimePatchException); Logger.Sources.Add(TraceLogSource.CreateSource()); Logger.Sources.Add(new HarmonyLogSource()); Logger.Listeners.Add(new ConsoleLogListener()); PreloaderLog = new PreloaderConsoleListener(); Logger.Listeners.Add(PreloaderLog); ChainloaderLogHelper.PrintLogInfo(Log); Log.LogInfo($"Running under Unity v{GetUnityVersion()}"); Log.LogInfo($"CLR runtime version: {Environment.Version}"); Log.LogInfo($"Supports SRE: {Utility.CLRSupportsDynamicAssemblies}"); Log.LogDebug($"Game executable path: {Paths.ExecutablePath}"); Log.LogDebug($"Unity Managed directory: {ManagedPath}"); Log.LogDebug($"BepInEx root path: {Paths.BepInExRootPath}"); if (runtimePatchException != null) { Log.LogWarning($"Failed to apply runtime patches for Mono. See more info in the output log. Error message: {runtimePatchException.Message}"); } Log.LogMessage("Preloader started"); TypeLoader.SearchDirectories.Add(ManagedPath); using (var assemblyPatcher = new AssemblyPatcher()) { assemblyPatcher.PatcherPlugins.Add(new PatcherPlugin { TargetDLLs = () => new[] { ConfigEntrypointAssembly.Value }, Patcher = PatchEntrypoint, TypeName = "BepInEx.Chainloader" }); assemblyPatcher.AddPatchersFromDirectory(Paths.PatcherPluginPath); Log.LogInfo($"{assemblyPatcher.PatcherPlugins.Count} patcher plugin{(assemblyPatcher.PatcherPlugins.Count == 1 ? "" : "s")} loaded"); assemblyPatcher.LoadAssemblyDirectory(ManagedPath); Log.LogInfo($"{assemblyPatcher.PatcherPlugins.Count} assemblies discovered"); assemblyPatcher.PatchAndLoad(); } Log.LogMessage("Preloader finished"); Logger.Listeners.Remove(PreloaderLog); PreloaderLog.Dispose(); Logger.Listeners.Add(new StdOutLogListener()); } catch (Exception ex) { try { Log.LogFatal("Could not run preloader!"); Log.LogFatal(ex); if (!ConsoleManager.ConsoleActive) { //if we've already attached the console, then the log will already be written to the console AllocateConsole(); Console.Write(PreloaderLog); } } catch { } var log = string.Empty; try { // We could use platform-dependent newlines, however the developers use Windows so this will be easier to read :) log = string.Join("\r\n", PreloaderConsoleListener.LogEvents.Select(x => x.ToString()).ToArray()); log += "\r\n"; PreloaderLog?.Dispose(); PreloaderLog = null; } catch { } File.WriteAllText( Path.Combine(Paths.GameRootPath, $"preloader_{DateTime.Now:yyyyMMdd_HHmmss_fff}.log"), log + ex); } }