public void RunMonoMod() { Environment.SetEnvironmentVariable("MONOMOD_DEPENDENCY_MISSING_THROW", "0"); if (this.verbosity > 0) { Environment.SetEnvironmentVariable("MONOMOD_LOG_VERBOSE", "1"); } using (MonoModder mm = new MonoModder() { InputPath = this.assemblyPath, OutputPath = AssemblyTmpPath, }) { // read assembly mm.Read(); // read Seshat.dll mm.ReadMod(this.seshatPath); mm.MapDependencies(); // autopatch mm.AutoPatch(); // write assembly mm.Write(); } }
/// <summary> /// Perform the actual patching of Assembly-CSharp.dll in the Risk of Rain 2 managed folder /// </summary> /// <param name="modPath">The path to the Assembly-CSharp.HexiDave.mm.dll file</param> private static void PatchWithMod(string modPath) { // Ensure that we have an Assembly-CSharp.dll.original file to work from FileUtilities.EnsureBackup(); // Get a temporary file to write the new assembly to var outputPath = Path.GetTempFileName(); // Setup MonoModder to patch the original Assembly-CSharp.dll using (var monoModder = new MonoModder { InputPath = FileUtilities.BackupAssemblyPath, OutputPath = outputPath }) { // Read the assembly monoModder.Read(); // Read the patch monoModder.ReadMod(modPath); // Ensure all the assembly references are still set monoModder.MapDependencies(); // Re-write assembly with patch functions monoModder.AutoPatch(); // Spit the file out monoModder.Write(); } // Clear the assembly in RoR2's managed folder File.Delete(FileUtilities.AssemblyPath); // Move the patched assembly into place File.Move(outputPath, FileUtilities.AssemblyPath); // Make sure any dependencies are moved // TODO: Maybe remove this, but still tinkering var filesToInclude = new[] { "Mono.Cecil.dll" }; foreach (var fileName in filesToInclude) { var moveToPath = $@"{FileUtilities.ManagedPath}\{fileName}"; if (!File.Exists(moveToPath)) { File.Move(fileName, moveToPath); } } }
/// <summary> /// Patches an assembly located in Managed. /// </summary> /// <param name="pathToPatch"></param> /// <param name="assemblyName"></param> public void PatchAssembly(string pathToPatch, string assemblyName, string[] dependencies) { string assemblyPath = FindAssemblyByName(assemblyName); if (assemblyPath == string.Empty) { return; } string outputPath = Path.Combine(Directory.GetParent(assemblyPath).FullName, Path.GetFileNameWithoutExtension(assemblyPath) + "-NEW.dll"); Console.WriteLine(assemblyPath); Console.WriteLine(outputPath); using (MonoModder mm = new MonoModder() { InputPath = assemblyPath, OutputPath = outputPath }) { mm.LogVerboseEnabled = true; mm.Read(); //Force everything to be public mm.PublicEverything = true; //Read in the patch mm.ReadMod(pathToPatch); mm.MapDependencies(); mm.DependencyDirs.Add(Directory.GetParent(Assembly.GetExecutingAssembly().FullName).FullName); mm.AutoPatch(); mm.Write(); } File.Delete(assemblyPath); File.Copy(outputPath, assemblyPath); File.Delete(outputPath); string managedPath = Directory.GetParent(assemblyPath).FullName; foreach (string s in dependencies) { string dependencyDestination = Path.Combine(managedPath, Path.GetFileName(s)); if (File.Exists(dependencyDestination)) { File.Delete(dependencyDestination); } File.Copy(s, dependencyDestination); } }
public static void LoadPatch(Stream stream) { try { ModLogger.Log("rtpatcher", "Loading new patch"); // Reload main assembly. Modder.Module = null; Modder.Read(); // Add new mod to mods list. Modder.ReadMod(stream); ModRelinker.AssemblyRelinkMap[Modder.Mods[Modder.Mods.Count - 1].Assembly.Name.Name] = ModRelinker.AssemblyRelinkedCache["Assembly-CSharp"]; Modder.MapDependencies(); // Auto-patch and then feed Harmony. ModLogger.Log("rtpatcher", $"Applying new patch {Modder.Mods[Modder.Mods.Count - 1].Assembly.Name.Name}"); Modder.AutoPatch(); MMHarmony.PatchAll(); } catch (Exception e) { ModLogger.Log("rtpatcher", $"Failed patching: {e}"); return; } }
public void Patch() { // Load the assembly to check if it needs to be patched first string assemblyPath = Path.Combine(_assemblyDirectory, AssemblyName); string assemblyBackupPath = assemblyPath.Replace(AssemblyName, AssemblyBackupName); if (!IsPatchingNeeded(assemblyPath)) { Console.WriteLine("Game is already patched, no further action required."); return; } // Copy the required assemblies to the game directory foreach (var assemblyName in PatchAssemblies) { File.Copy(assemblyName, Path.Combine(_assemblyDirectory, assemblyName), true); } File.Copy(assemblyPath, assemblyBackupPath, true); // Run MonoMod Console.WriteLine("Patching game..."); using (MonoModder mm = new MonoModder() { InputPath = assemblyBackupPath, OutputPath = assemblyPath + ".tmp" }) { Environment.SetEnvironmentVariable("MONOMOD_DEPENDENCY_MISSING_THROW", "0"); mm.Read(); mm.ReadMod(Path.Combine(_assemblyDirectory, AssemblyPatchName)); mm.MapDependencies(); mm.AutoPatch(); mm.Write(); } // Copy the resultant assembly File.Delete(assemblyPath); File.Move(assemblyPath + ".tmp", assemblyPath); }
public static bool Mod(this InstallerWindow ins, string file) { string inPath = Path.Combine(ins.MainModDir, file); string outPath = Path.Combine(ins.MainModDir, file + ".tmp.dll"); MonoModder monomod = new MonoModder() { InputPath = inPath, OutputPath = outPath }; monomod.SetupETGModder(); using (FileStream fileStream = File.Open(LogPath, FileMode.Append)) { using (StreamWriter streamWriter = new StreamWriter(fileStream)) { monomod.Logger = (string s) => ins.OnActivity(); monomod.Logger += (string s) => streamWriter.WriteLine(s); // Unity wants .mdbs // monomod.WriterParameters.SymbolWriterProvider = new Mono.Cecil.Mdb.MdbWriterProvider(); string db = Path.ChangeExtension(inPath, "pdb"); string dbTmp = Path.ChangeExtension(outPath, "pdb"); if (!File.Exists(db)) { db = inPath + ".mdb"; dbTmp = outPath + ".mdb"; } #if !DEBUG RETRY: try { #endif monomod.Read(); // Read main module first monomod.ReadMod(Directory.GetParent(inPath).FullName); // ... then mods monomod.MapDependencies(); // ... then all dependencies monomod.AutoPatch(); // Patch, monomod.Write(); // and write. monomod.Dispose(); // Finally, dispose, because file access happens now. File.Delete(inPath); File.Move(outPath, inPath); if (File.Exists(db)) { File.Delete(db); } if (File.Exists(dbTmp)) { File.Move(dbTmp, db); } return(true); #if !DEBUG } catch (ArgumentException e) { monomod.Dispose(); if (File.Exists(db)) { File.Delete(db); if (File.Exists(dbTmp)) { File.Delete(dbTmp); } goto RETRY; } ins.LogLine(e.ToString()); throw; return(false); } catch (Exception e) { monomod.Dispose(); ins.LogLine(e.ToString()); throw; return(false); } #endif } } }
public static void Main(string[] args) { Console.WriteLine("MonoMod " + System.Reflection.Assembly.GetExecutingAssembly().GetName().Version); if (args.Length == 0) { Console.WriteLine("No valid arguments (assembly path) passed."); if (System.Diagnostics.Debugger.IsAttached) // Keep window open when running in IDE { Console.ReadKey(); } return; } string pathIn; string pathOut; if (args.Length > 1 && args[0] == "--generate-debug-il" || args[0] == "--gen-dbg-il") { Console.WriteLine("[DbgILGen] Generating debug hierarchy and debug data (pdb / mdb)."); pathIn = args[1]; pathOut = args.Length != 2 ? args[args.Length - 1] : Path.Combine(Path.GetDirectoryName(pathIn), "MMDBGIL_" + Path.GetFileName(pathIn)); using (MonoModder mm = new MonoModder() { InputPath = pathIn, OutputPath = pathOut }) { mm.Read(false); mm.Log("[DbgILGen] DebugILGenerator.Generate(mm);"); DebugILGenerator.Generate(mm); mm.Write(); mm.Log("[DbgILGen] Done."); } if (System.Diagnostics.Debugger.IsAttached) // Keep window open when running in IDE { Console.ReadKey(); } return; } int pathInI = 0; for (int i = 0; i < args.Length; i++) { if (args[i] == "--dependency-missing-throw=0" || args[i] == "--lean-dependencies") { Environment.SetEnvironmentVariable("MONOMOD_DEPENDENCY_MISSING_THROW", "0"); pathInI = i + 1; } else if (args[i] == "--cleanup=0" || args[i] == "--skip-cleanup") { Environment.SetEnvironmentVariable("MONOMOD_CLEANUP", "0"); pathInI = i + 1; } else if (args[i] == "--cleanup-all=1" || args[i] == "--cleanup-all") { Environment.SetEnvironmentVariable("MONOMOD_CLEANUP_ALL", "1"); pathInI = i + 1; } else if (args[i] == "--verbose=1" || args[i] == "--verbose" || args[i] == "-v") { Environment.SetEnvironmentVariable("MONOMOD_VERBOSE", "1"); pathInI = i + 1; } } if (pathInI >= args.Length) { Console.WriteLine("No assembly path passed."); if (System.Diagnostics.Debugger.IsAttached) // Keep window open when running in IDE { Console.ReadKey(); } return; } pathIn = args[pathInI]; pathOut = args.Length != 1 && pathInI != args.Length - 1 ? args[args.Length - 1] : Path.Combine(Path.GetDirectoryName(pathIn), "MONOMODDED_" + Path.GetFileName(pathIn)); if (File.Exists(pathOut)) { File.Delete(pathOut); } try { using (MonoModder mm = new MonoModder() { InputPath = pathIn, OutputPath = pathOut, Verbose = Environment.GetEnvironmentVariable("MONOMOD_VERBOSE") == "1" }) { mm.Read(false); if (args.Length <= 2) { mm.Log("[Main] Scanning for mods in directory."); mm.ReadMod(Directory.GetParent(pathIn).FullName); } else { mm.Log("[Main] Reading mods list from arguments."); for (int i = pathInI + 1; i < args.Length - 2; i++) { mm.ReadMod(args[i]); } } mm.Read(true); mm.Log("[Main] mm.AutoPatch();"); mm.AutoPatch(); mm.Write(); mm.Log("[Main] Done."); } } catch (Exception e) { Console.WriteLine(e); } if (System.Diagnostics.Debugger.IsAttached) // Keep window open when running in IDE { Console.ReadKey(); } }
public static int Main(string[] args) { Console.WriteLine("MonoMod " + typeof(Program).GetTypeInfo().Assembly.GetName().Version); if (args.Length == 0) { Console.WriteLine("No valid arguments (assembly path) passed."); if (System.Diagnostics.Debugger.IsAttached) // Keep window open when running in IDE { Console.ReadKey(); } return(0); } string pathIn; string pathOut; int pathInI = 0; for (int i = 0; i < args.Length; i++) { if (args[i] == "--dependency-missing-throw=0" || args[i] == "--lean-dependencies") { Environment.SetEnvironmentVariable("MONOMOD_DEPENDENCY_MISSING_THROW", "0"); pathInI = i + 1; } else if (args[i] == "--cleanup=0" || args[i] == "--skip-cleanup") { Environment.SetEnvironmentVariable("MONOMOD_CLEANUP", "0"); pathInI = i + 1; } else if (args[i] == "--cleanup-all=1" || args[i] == "--cleanup-all") { Environment.SetEnvironmentVariable("MONOMOD_CLEANUP_ALL", "1"); pathInI = i + 1; } else if (args[i] == "--verbose=1" || args[i] == "--verbose" || args[i] == "-v") { Environment.SetEnvironmentVariable("MONOMOD_LOG_VERBOSE", "1"); pathInI = i + 1; } else if (args[i] == "--cache=0" || args[i] == "--uncached") { Environment.SetEnvironmentVariable("MONOMOD_RELINKER_CACHED", "0"); pathInI = i + 1; } } if (pathInI >= args.Length) { Console.WriteLine("No assembly path passed."); if (System.Diagnostics.Debugger.IsAttached) // Keep window open when running in IDE { Console.ReadKey(); } return(0); } pathIn = args[pathInI]; pathOut = args.Length != 1 && pathInI != args.Length - 1 ? args[args.Length - 1] : null; pathOut = pathOut ?? Path.Combine(Path.GetDirectoryName(pathIn), "MONOMODDED_" + Path.GetFileName(pathIn)); if (File.Exists(pathOut)) { File.Delete(pathOut); } #if !DEBUG try { #endif using (MonoModder mm = new MonoModder() { InputPath = pathIn, OutputPath = pathOut }) { mm.Read(); if (args.Length <= 2) { mm.Log("[Main] Scanning for mods in directory."); mm.ReadMod(Directory.GetParent(pathIn).FullName); } else { mm.Log("[Main] Reading mods list from arguments."); for (int i = pathInI + 1; i < args.Length - 1; i++) { mm.ReadMod(args[i]); } } mm.MapDependencies(); mm.Log("[Main] mm.AutoPatch();"); mm.AutoPatch(); mm.Write(); mm.Log("[Main] Done."); } #if !DEBUG } catch (Exception e) { Console.WriteLine(e); if (System.Diagnostics.Debugger.IsAttached) // Keep window open when running in IDE { Console.ReadKey(); } return(-1); } #endif if (System.Diagnostics.Debugger.IsAttached) // Keep window open when running in IDE { Console.ReadKey(); } return(0); }
public void Install(Installer installer, bool leave_mmdlls = false) { var managed = installer.ManagedDir; if (HasPluginsDir) { _InstallPlugins(installer.PluginsDir); } if (RequiresPatchedExe) { installer.PatchExe(); } using (StreamWriter patches_info_writer = new StreamWriter(File.OpenWrite(installer.PatchesInfoFile))) { patches_info_writer.WriteLine($"{Name} {VersionName}"); } _Install("assembly", Assemblies, managed); _Install("MonoMod patch DLL", PatchDLLs, managed); _Install("file", OtherFiles, managed, subdir: true); _Install("directory", Dirs, managed, subdir: true); foreach (var patch_target in Metadata?.OrderedTargets ?? installer.Downloader.GungeonMetadata.ViablePatchTargets) { var patch_target_dll = Path.Combine(managed, $"{patch_target}.dll"); var patch_target_tmp = Path.Combine(managed, $"{patch_target}{TMP_PATCH_SUFFIX}"); var modder = new MonoModder { InputPath = patch_target_dll, OutputPath = patch_target_tmp }; if (Metadata != null && Metadata.RelinkMap != null) { Dictionary <string, string> rmap; if (Metadata.RelinkMap.TryGetValue(patch_target, out rmap)) { _Logger.Info($"Reading component relink map for target {patch_target}"); foreach (var pair in rmap) { ModuleDefinition module; if (!modder.DependencyCache.TryGetValue(pair.Value, out module)) { var path = Path.Combine(managed, pair.Value); _Logger.Debug($"Dependency not in cache: {pair.Value} ({path})"); module = modder.DependencyCache[pair.Value] = ModuleDefinition.ReadModule(path); } _Logger.Debug($"Mapping {pair.Key} => {pair.Value}"); modder.RelinkModuleMap[pair.Key] = module; } } } modder.Read(); var found_mods = false; foreach (var dll in PatchDLLs) { if (File.Exists(Path.Combine(managed, dll)) && dll.StartsWith($"{patch_target}.", StringComparison.InvariantCulture)) { found_mods = true; _Logger.Debug($"Using patch DLL: {dll}"); modder.ReadMod(Path.Combine(managed, dll)); } } if (!found_mods) { _Logger.Info($"Not patching {patch_target} because this component has no patches for it"); continue; } _Logger.Info($"Patching target: {patch_target}"); modder.MapDependencies(); modder.AutoPatch(); modder.Write(); modder.Dispose(); _Logger.Debug($"Replacing original ({patch_target_tmp} => {patch_target_dll})"); if (File.Exists(patch_target_dll)) { File.Delete(patch_target_dll); } File.Move(patch_target_tmp, patch_target_dll); } if (!leave_mmdlls) { foreach (var dll in PatchDLLs) { if (!File.Exists(Path.Combine(managed, dll))) { continue; } _Logger.Debug($"Cleaning up patch DLL {dll}"); File.Delete(Path.Combine(managed, dll)); } } _Logger.Debug($"Cleaning up patched DLL MDB/PDBs"); foreach (var ent in Directory.GetFileSystemEntries(managed)) { if (ent.EndsWith($"{TMP_PATCH_SUFFIX}.mdb", StringComparison.InvariantCulture)) { File.Delete(ent); } } }
public static int Main(string[] args) { Console.WriteLine("MonoMod " + System.Reflection.Assembly.GetExecutingAssembly().GetName().Version); if (args.Length == 0) { Console.WriteLine("No valid arguments (assembly path) passed."); if (System.Diagnostics.Debugger.IsAttached) // Keep window open when running in IDE { Console.ReadKey(); } return(0); } if (args[0] == "--test") { Console.WriteLine("[QuickDebugTest] Running..."); int result = QuickDebugTest.Run(args); if (result == 0) { Console.WriteLine("[QuickDebugTest] Passed!"); } else { Console.WriteLine($"[QuickDebugTest] Failed: {result}"); } if (System.Diagnostics.Debugger.IsAttached) // Keep window open when running in IDE { Console.ReadKey(); } return(result); } string pathIn; string pathOut; int pathInI = 0; bool generateDebugIL = false; for (int i = 0; i < args.Length; i++) { if (args[i] == "--dependency-missing-throw=0" || args[i] == "--lean-dependencies") { Environment.SetEnvironmentVariable("MONOMOD_DEPENDENCY_MISSING_THROW", "0"); pathInI = i + 1; } else if (args[i] == "--cleanup=0" || args[i] == "--skip-cleanup") { Environment.SetEnvironmentVariable("MONOMOD_CLEANUP", "0"); pathInI = i + 1; } else if (args[i] == "--cleanup-all=1" || args[i] == "--cleanup-all") { Environment.SetEnvironmentVariable("MONOMOD_CLEANUP_ALL", "1"); pathInI = i + 1; } else if (args[i] == "--verbose=1" || args[i] == "--verbose" || args[i] == "-v") { Environment.SetEnvironmentVariable("MONOMOD_LOG_VERBOSE", "1"); pathInI = i + 1; } else if (args[i] == "--cache=0" || args[i] == "--uncached") { Environment.SetEnvironmentVariable("MONOMOD_RELINKER_CACHED", "0"); pathInI = i + 1; } else if (args[i] == "--generate-debug-il" || args[i] == "--gen-dbg-il") { generateDebugIL = true; pathInI = i + 1; } else if (args[i] == "--debug-il-relative" || args[i] == "--dbg-il-relative") { Environment.SetEnvironmentVariable("MONOMOD_DEBUGIL_RELATIVE", "1"); pathInI = i + 1; } } if (pathInI >= args.Length) { Console.WriteLine("No assembly path passed."); if (System.Diagnostics.Debugger.IsAttached) // Keep window open when running in IDE { Console.ReadKey(); } return(0); } pathIn = args[pathInI]; pathOut = args.Length != 1 && pathInI != args.Length - 1 ? args[args.Length - 1] : null; if (generateDebugIL) { Console.WriteLine("[DbgILGen] Generating debug hierarchy and debug data (pdb / mdb)."); pathOut = pathOut ?? Path.Combine(Path.GetDirectoryName(pathIn), "MMDBGIL_" + Path.GetFileName(pathIn)); using (MonoModder mm = new MonoModder() { InputPath = pathIn, OutputPath = pathOut }) { mm.Read(); mm.Log("[DbgILGen] DebugILGenerator.Generate(mm);"); DebugILGenerator.Generate(mm); mm.Write(); mm.Log("[DbgILGen] Done."); } if (System.Diagnostics.Debugger.IsAttached) // Keep window open when running in IDE { Console.ReadKey(); } return(0); } pathOut = pathOut ?? Path.Combine(Path.GetDirectoryName(pathIn), "MONOMODDED_" + Path.GetFileName(pathIn)); if (File.Exists(pathOut)) { File.Delete(pathOut); } #if !DEBUG try { #endif using (MonoModder mm = new MonoModder() { InputPath = pathIn, OutputPath = pathOut }) { mm.Read(); if (args.Length <= 2) { mm.Log("[Main] Scanning for mods in directory."); mm.ReadMod(Directory.GetParent(pathIn).FullName); } else { mm.Log("[Main] Reading mods list from arguments."); for (int i = pathInI + 1; i < args.Length - 1; i++) { mm.ReadMod(args[i]); } } mm.MapDependencies(); mm.Log("[Main] mm.AutoPatch();"); mm.AutoPatch(); mm.Write(); mm.Log("[Main] Done."); } #if !DEBUG } catch (Exception e) { Console.WriteLine(e); if (System.Diagnostics.Debugger.IsAttached) // Keep window open when running in IDE { Console.ReadKey(); } return(-1); } #endif if (System.Diagnostics.Debugger.IsAttached) // Keep window open when running in IDE { Console.ReadKey(); } return(0); }