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 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); } } }