private static bool PatchUnityExe(string managedDir, string unityOutputDLL, out string message) { message = null; try { var injectedDLL = Path.GetFullPath($"{managedDir}\\BepInEx.Bootstrap.dll"); File.WriteAllBytes(injectedDLL, EmbeddedResource.Get("BepInEx.Patcher.BepInEx.Bootstrap.dll")); var defaultResolver = new DefaultAssemblyResolver(); defaultResolver.AddSearchDirectory(managedDir); var rp = new ReaderParameters { AssemblyResolver = defaultResolver }; var unityBackupDLL = $"{GetUnityEngineAssembly(managedDir)}.bak"; //determine which assembly to use as a base var unity = AssemblyDefinition.ReadAssembly(unityOutputDLL, rp); if (!VerifyAssembly(unity, out message)) { //try and fall back to .bak if exists if (File.Exists(unityBackupDLL)) { unity.Dispose(); unity = AssemblyDefinition.ReadAssembly(unityBackupDLL, rp); if (!VerifyAssembly(unity, out message)) { //can't use anything unity.Dispose(); message += "\r\nThe backup is not usable."; return(false); } } else { //can't use anything unity.Dispose(); message += "\r\nNo backup exists."; return(false); } } else { //make a backup of the assembly File.Copy(unityOutputDLL, unityBackupDLL, true); unity.Dispose(); unity = AssemblyDefinition.ReadAssembly(unityBackupDLL, rp); } //patch using (unity) using (var injected = AssemblyDefinition.ReadAssembly(injectedDLL, rp)) { InjectAssembly(unity, injected); unity.Write(unityOutputDLL); } } catch (Exception e) { message = e.ToString(); return(false); } return(true); }