private bool IsPatched(string assemblyToPatch, string assemblyType, string assemblyMethod, string loaderAssembly, string loaderType, string loaderMethod) { ModuleDefinition assembly = ModuleDefinition.ReadModule(assemblyToPatch); ModuleDefinition loader = ModuleDefinition.ReadModule(loaderAssembly); MethodDefinition methodToInject = loader.GetType(loaderType).Methods.Single(x => x.Name == loaderMethod); MethodDefinition methodToHook = assembly.GetType(assemblyType) .Methods.First(x => x.Name == assemblyMethod); foreach (Instruction instruction in methodToHook.Body.Instructions) { if (instruction.OpCode.Equals(OpCodes.Call) && instruction.Operand.ToString().Equals( $"System.Void {loaderType}::{loaderMethod}()")) { assembly.Dispose(); loader.Dispose(); return(true); } } assembly.Dispose(); loader.Dispose(); return(false); }
private static HalfInjected InjectionFirstStep(string path, string className, string methodName, string debugPre = "", bool isGeneric = false) { if (!File.Exists(path)) { Console.WriteLine(debugPre + "Could not find Assembly-CSharp.dll at path \"" + path + "\""); return(null); } ModuleDefinition module = ModuleDefinition.ReadModule(path, new ReaderParameters() { ReadWrite = true }); TypeDefinition type = module.GetType(className); if (type == null) { Console.WriteLine(debugPre + "Could not find class \"" + className + "\""); module.Dispose(); return(null); } MethodDefinition targetMethod = type.Methods.FirstOrDefault(method => method.Name == methodName && method.ContainsGenericParameter == isGeneric); if (targetMethod == null) { Console.WriteLine(debugPre + "Could not find Method \"" + methodName + "\" in class \"" + className + "\""); module.Dispose(); return(null); } ILProcessor iLProcessor = targetMethod.Body.GetILProcessor(); return(new HalfInjected(module, targetMethod, type, iLProcessor)); }
public static ModTypes GetModType(FileInfo modFile) { ModuleDefinition modDef = ModuleDefinition.ReadModule(modFile.FullName); Type patchType = typeof(MonoMod.MonoModPatch); //Foreach type in the mod dll foreach (TypeDefinition checkType in modDef.GetTypes()) { //If the type has a custom attribute if (checkType.HasCustomAttributes) { HashSet <CustomAttribute> attributes = new HashSet <CustomAttribute>(checkType.CustomAttributes); //Foreach custom attribute foreach (CustomAttribute ct in attributes) { //If the attribute is [MonoModPatch] if (ct.AttributeType.Name == patchType.Name) { modDef.Dispose(); return(ModTypes.Patch); } } } } modDef.Dispose(); return(ModTypes.Mod); }
public static void AddMethodToClass(string pathToWriteTo, string classToWriteTo, string newMethodName, string pathToCopyFrom, string classToCopyFrom, string methodToCopyFrom) { HalfInjected copy = InjectionFirstStep(pathToCopyFrom, classToCopyFrom, methodToCopyFrom, " copy: "); if (!File.Exists(pathToWriteTo)) { Console.WriteLine("paste: Could not find Assembly-CSharp.dll at path \"" + pathToWriteTo + "\""); return; } ModuleDefinition writeModule = ModuleDefinition.ReadModule(pathToWriteTo, new ReaderParameters() { ReadWrite = true }); TypeDefinition typeToWriteTo = writeModule.GetType(classToWriteTo); if (typeToWriteTo == null) { copy.Module.Dispose(); Console.WriteLine("Write: Could not find class \"" + classToWriteTo + "\""); return; } if (typeToWriteTo.Methods.Where(a => a.Name == newMethodName).Count() >= 1) { copy.Module.Dispose(); writeModule.Dispose(); Console.WriteLine("Method \"" + newMethodName + "\" already exists, skipping!"); return; } TypeReference returnType = writeModule.ImportReference(copy.TargetMethod.ReturnType); MethodDefinition newMethod = new MethodDefinition(newMethodName, copy.TargetMethod.Attributes, returnType); newMethod.Parameters.Clear(); for (int i = 0; i < copy.TargetMethod.Parameters.Count; i++) { newMethod.Parameters.Add(copy.TargetMethod.Parameters[i]); } List <AssemblyNameReference> differance = Util.GetDifferenceBetweenLists(copy.Module.AssemblyReferences.ToList(), writeModule.AssemblyReferences.ToList()); Console.WriteLine("Adding references to assemblies:"); for (int i = 0; i < differance.Count; i++) { Console.WriteLine("\t" + differance[i].FullName); copy.Module.AssemblyReferences.Add(differance[i]); } OverwriteMethodIL(newMethod, copy.TargetMethod, classToWriteTo, newMethodName, writeModule, typeToWriteTo); typeToWriteTo.Methods.Add(newMethod); writeModule.Write(); writeModule.Dispose(); copy.Module.Dispose(); Console.WriteLine("Added method \"" + classToWriteTo + "." + newMethodName + "\" from \"" + classToCopyFrom + "." + methodToCopyFrom + "\""); }
bool NeedsPatch(string targetPath, string alreadyInstalledType) { ModuleDefinition module = ModuleDefinition.ReadModule(targetPath); foreach (TypeDefinition type in module.Types) { if (type.FullName == alreadyInstalledType) { module.Dispose(); return(false); } } module.Dispose(); return(true); }
private void PatchThis(string mainPath, string assemblyToPatch, string assemblyType, string assemblyMethod, string loaderAssembly, string loaderType, string loaderMethod) { DefaultAssemblyResolver resolver = new DefaultAssemblyResolver(); resolver.AddSearchDirectory(mainPath); ModuleDefinition assembly = ModuleDefinition.ReadModule( mainPath + "/" + assemblyToPatch, new ReaderParameters { ReadWrite = true, AssemblyResolver = resolver }); ModuleDefinition loader = ModuleDefinition.ReadModule(mainPath + "/" + loaderAssembly); MethodDefinition methodToInject = loader.GetType(loaderType).Methods.Single(x => x.Name == loaderMethod); MethodDefinition methodToHook = assembly.GetType(assemblyType) .Methods.First(x => x.Name == assemblyMethod); Instruction loaderInit = Instruction.Create(OpCodes.Call, assembly.ImportReference(methodToInject)); ILProcessor processor = methodToHook.Body.GetILProcessor(); processor.InsertBefore(methodToHook.Body.Instructions[0], loaderInit); assembly.Write(); assembly.Dispose(); loader.Dispose(); }
private void UpdateModule(ModuleDefinition moduleDefinition) { var fileName = moduleDefinition.FileName; using (var writer = File.Create(fileName + "_new")) { moduleDefinition.Write(writer); } moduleDefinition.Dispose(); if (File.Exists(fileName + "_old")) { File.Delete(fileName + "_old"); } File.Move(fileName, fileName + "_old"); try { File.Move(fileName + "_new", fileName); } catch (Exception) { throw new ArgumentException($"The assembly '{fileName}' is locked!"); } }
public void Dispose() { _resolver.Dispose(); _resolver = null; _assembly.Dispose(); _assembly = null; }
public void Execute() { ResolveEventHandler assemblyResolve = CurrentDomain_AssemblyResolve; try { SplitUpReferences(); GetSymbolProviders(); assemblyResolver = new AssemblyResolver(Logger, SplitReferences); ReadModule(); AppDomain.CurrentDomain.AssemblyResolve += assemblyResolve; InitialiseWeavers(); ExecuteWeavers(); AddWeavingInfo(); FindStrongNameKey(); WriteModule(); ModuleDefinition?.Dispose(); CleanupTempSymbolsAndAssembly(); ExecuteAfterWeavers(); DisposeWeavers(); } catch (Exception exception) { AppDomain.CurrentDomain.AssemblyResolve -= assemblyResolve; Logger.LogException(exception); } finally { ModuleDefinition?.Dispose(); CleanupTempSymbolsAndAssembly(); assemblyResolver?.Dispose(); } }
public void Reload() { MethodBase orig = OriginalMethod; if (orig == null) { throw new InvalidOperationException(); } ModuleDefinition module = null; try { _Definition = null; #if !CECIL0_9 _Module?.Dispose(); #endif _Module = null; Type[] argTypes; ParameterInfo[] args = orig.GetParameters(); int offs = 0; if (!orig.IsStatic) { offs++; argTypes = new Type[args.Length + 1]; argTypes[0] = orig.GetThisParamType(); } else { argTypes = new Type[args.Length]; } for (int i = 0; i < args.Length; i++) { argTypes[i + offs] = args[i].ParameterType; } module = _CreateDynModule(orig.GetID(simple: true), (orig as MethodInfo)?.ReturnType, argTypes); _CopyMethodToDefinition(); MethodDefinition def = Definition; if (!orig.IsStatic) { def.Parameters[0].Name = "this"; } for (int i = 0; i < args.Length; i++) { def.Parameters[i + offs].Name = args[i].Name; } _Module = module; module = null; } catch { #if !CECIL0_9 module?.Dispose(); #endif throw; } }
/// <summary> /// Dispose all loaded modules. /// </summary> public void Dispose() { foreach (var assemblyPair in Assemblies.Values) { assemblyPair.Item2.Dispose(); } Module.Dispose(); }
public void Dispose() { if (_IsDisposed) { return; } _IsDisposed = true; _Module.Dispose(); }
public void Reload(Func <AssemblyName, ModuleDefinition> moduleGen = null, bool forceModule = false) { ModuleDefinition moduleTmp = null; if (moduleGen != null) { _ModuleGen = moduleGen; } try { _Definition = null; ModuleDefinition module = (moduleGen ?? _ModuleGen)?.Invoke(Method.Module.Assembly.GetName()); lock (_ModuleRefs) { if (module == null) { if (_Module != null && !forceModule) { module = _Module; } else { #if !CECIL0_9 _Module?.Dispose(); #endif _Module = null; } ReaderParameters rp = new ReaderParameters(); if (_ModuleGen != null) { rp.AssemblyResolver = new AssemblyCecilDefinitionResolver(_ModuleGen, rp.AssemblyResolver ?? new DefaultAssemblyResolver()); } module = moduleTmp = ModuleDefinition.ReadModule(Method.DeclaringType.GetTypeInfo().Assembly.GetLocation(), rp); } _Module = module; _ModuleRef++; } _Definition = Definition; } catch when(_DisposeEarly()) { } bool _DisposeEarly() { if (moduleTmp != null) { lock (_ModuleRefs) { #if !CECIL0_9 moduleTmp.Dispose(); #endif _Module = null; _ModuleRef = 0; } } return(false); } }
public void TearDown() { //HACK: put the Log callbacks back the way they were Log.LogDebugAction = null; Log.LogWarningAction = null; Log.LogErrorAction = null; module.Dispose(); File.Delete(temporaryAssembly); File.Delete(inputFile); File.Delete(outputFile); }
public void Dispose() { if (test_module != null) { test_module.Dispose(); } if (test_resolver != null) { test_resolver.Dispose(); } }
private bool disposedValue = false; // To detect redundant calls protected virtual void Dispose(bool disposing) { if (!disposedValue) { if (disposing) { module.Dispose(); } disposedValue = true; } }
static ModuleDefinition RoundtripModule(ModuleDefinition module, RoundtripType roundtripType) { if (roundtripType == RoundtripType.None) { return(module); } var file = Path.Combine(Path.GetTempPath(), "TestILProcessor.dll"); if (File.Exists(file)) { File.Delete(file); } ISymbolWriterProvider symbolWriterProvider; switch (roundtripType) { case RoundtripType.Pdb when Platform.HasNativePdbSupport: symbolWriterProvider = new PdbWriterProvider(); break; case RoundtripType.PortablePdb: default: symbolWriterProvider = new PortablePdbWriterProvider(); break; } module.Write(file, new WriterParameters { SymbolWriterProvider = symbolWriterProvider, }); module.Dispose(); ISymbolReaderProvider symbolReaderProvider; switch (roundtripType) { case RoundtripType.Pdb when Platform.HasNativePdbSupport: symbolReaderProvider = new PdbReaderProvider(); break; case RoundtripType.PortablePdb: default: symbolReaderProvider = new PortablePdbReaderProvider(); break; } return(ModuleDefinition.ReadModule(file, new ReaderParameters { SymbolReaderProvider = symbolReaderProvider, InMemory = true })); }
static void Main() { string managedPath = PathDiscovery.FindManagedDirectory(); var resolver = new DefaultAssemblyResolver(); resolver.AddSearchDirectory(managedPath); Version version = GetUnityVersion(); // as of Unity 2017.2, the UnityEngine assembly has been split into multiple assemblies // the assembly containing the GameObject class is UnityEngine.CoreModule string coreName = version.Major < 2017 || (version.Major == 2017 && version.Minor == 1) ? "UnityEngine" : "UnityEngine.CoreModule"; string corePath = PathDiscovery.GetAssemblyPath(resolver, coreName); byte[] coreData = File.ReadAllBytes(corePath); Console.WriteLine("Unity {0} detected.", version); ModuleDefinition unityCore = ModuleDefinition.ReadModule( new MemoryStream(coreData), new ReaderParameters { AssemblyResolver = resolver }); TypeDefinition gameObject = unityCore.GetType("UnityEngine", "GameObject"); // UPM works by adding a static constructor to the GameObject class, // which calls an initialization function in PluginManager.Core SetStaticCtor(gameObject, GenStaticCtor(unityCore, il => { ModuleDefinition upm = ModuleDefinition.ReadModule(CoreLibrary); TypeDefinition upmMain = upm.GetType("PluginManager.Core", "PluginManager"); MethodDefinition upmInit = upmMain.Methods.Single(m => m.Name == "Initialize"); il.Emit(OpCodes.Call, unityCore.ImportReference(upmInit)); il.Emit(OpCodes.Ret); upm.Dispose(); })); unityCore.Write(corePath); // We need to copy PluginManager.Core.dll into the Managed directory File.Copy(CoreLibrary, Path.Combine(managedPath, CoreLibrary), true); Console.WriteLine("UPM installed."); }
private void GatherAssemblyInfo(string p) { try { ModuleDefinition module = ModuleDefinition.ReadModule(p); if (null == baseTypeDefiniation) { baseTypeDefiniation = module.GetType("Tizen.NUI.Binding.BindableObject"); } foreach (var attr in module.Assembly.CustomAttributes) { if (attr.AttributeType.FullName == "Tizen.NUI.XmlnsDefinitionAttribute") { string xmlNamespace = attr.ConstructorArguments[0].Value as string; string clrNamespace = attr.ConstructorArguments[1].Value as string; int level = 0; string assemblyName = module.Assembly.FullName; if (true == attr.HasProperties) { foreach (var property in attr.Properties) { if ("Level" == property.Name) { level = int.Parse(property.Argument.Value.ToString()); } if ("AssemblyName" == property.Name) { assemblyName = property.Argument.Value as string; } } } XmlnsDefinitionAttribute attribute = new XmlnsDefinitionAttribute(xmlNamespace, clrNamespace, level); attribute.AssemblyName = assemblyName; s_xmlnsDefinitions.Add(attribute); } } module.Dispose(); } catch (Exception e) { int temp = 0; } }
public static void Weave(string[] assemblyPaths) { var modules = new List <ModuleDefinition>(); ModuleDefinition demonModule = null; try { demonModule = HackyLoadDemonModule(); var demonTypes = DemonTypes.FromModule(demonModule); foreach (var path in assemblyPaths) { modules.Add(ModuleDefinition.ReadModule(path, new ReaderParameters { ReadWrite = true })); } var allTypes = modules.SelectMany(m => m.GetTypes()).ToList(); var advice = AspectModelBuilder.FromTypeDefinitions(allTypes); //todo filter to not run on aspects accidentally foreach (var type in allTypes) { TypeWeaver.Weave(type, advice, demonTypes); } //todo check file locking issues foreach (var module in modules) { module.Write(); } } finally { foreach (var module in modules) { module.Dispose(); } demonModule?.Dispose(); } }
public static int Main(string[] args) { if (args.Length < 3) { Console.Error.WriteLine("usage: BurstPatcher.exe <input assembly path> <output assembly path> <response file to write for burst>"); return(1); } var resolver = new DefaultAssemblyResolver(); var p = System.IO.Path.GetDirectoryName(args[0]); /* * the assemblies provided to the patcher are assumed to have their dependencies next to them */ resolver.AddSearchDirectory(p); var pdbPath = Path.ChangeExtension(args[0], "pdb"); bool readSymbols = File.Exists(pdbPath); ModuleDefinition module = ModuleDefinition.ReadModule(args[0], new ReaderParameters { ReadSymbols = readSymbols, AssemblyResolver = resolver }); foreach (TypeDefinition type in module.Types) { VisitMethods(type); } module.Write(args[1], new WriterParameters { WriteSymbols = readSymbols }); module.Dispose(); if (burstargs.Count == 0) { FileStream myFileStream = File.Open(args[2], FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite); myFileStream.Close(); myFileStream.Dispose(); File.SetLastWriteTimeUtc(args[2], DateTime.UtcNow); return(0); } System.IO.File.WriteAllLines(args[2], burstargs); return(0); }
public void Execute() { ResolveEventHandler assemblyResolve = CurrentDomain_AssemblyResolve; try { SplitUpReferences(); GetSymbolProviders(); assemblyResolver = new AssemblyResolver(Logger, SplitReferences); ReadModule(); if (ModuleDefinition.Types.Any(x => x.Name == "ProcessedByFody")) { Logger.LogWarning($"The assembly has already been processed by Fody. Weaving aborted. Path: {AssemblyFilePath} "); return; } AppDomain.CurrentDomain.AssemblyResolve += assemblyResolve; TypeCache = new TypeCache(assemblyResolver.Resolve); InitialiseWeavers(); TypeCache.BuildAssembliesToScan(weaverInstances.Select(x => x.Instance)); InitialiseTypeSystem(); ExecuteWeavers(); AddWeavingInfo(); FindStrongNameKey(); WriteModule(); ModuleDefinition?.Dispose(); CleanupTempSymbolsAndAssembly(); ExecuteAfterWeavers(); DisposeWeavers(); } catch (Exception exception) { AppDomain.CurrentDomain.AssemblyResolve -= assemblyResolve; Logger.LogException(exception); } finally { ModuleDefinition?.Dispose(); CleanupTempSymbolsAndAssembly(); assemblyResolver?.Dispose(); } }
public static void SavePatchedFile(ModuleDefinition module, string fileName, bool disposeModule) { try { module.Write(fileName); if (disposeModule) { module.Dispose(); } } catch (AssemblyResolutionException) { ErrorHandler.TerminateWithError("Can't find the required dependencies. Make sure you run Prism inside the 'Managed' directory.", TerminationReason.RequiredDependenciesMissing); } catch (Exception e) { ErrorHandler.TerminateWithError($"Can't write back the modified assembly. Is it in use and/or you don't have write rights?\n{e}", TerminationReason.AssemblySaveFailed); } }
/// <summary> /// Questa funzione modifica la chiave di licenza nella DLL /// </summary> /// <returns></returns> private static bool patchFile() { bool result = false; try { //Carico la dll da patchare e in particolare l'oggetto Class1 using ModuleDefinition module = ModuleDefinition.ReadModule(@$ "{Directory.GetCurrentDirectory()}\..\..\..\..\Reflection.Example\bin\Debug\netcoreapp3.1\Reflection.Example.Shared.dll"); TypeDefinition myType = module.Types.First(type => type.Name == "Class1"); //Mi posiziono sul costruttore... te la spiego la prossima volta.. intanto ricordati che è sdove viene impostato il valore "licenza" MethodDefinition ctor = myType.Methods.First(prop => prop.Name == ".ctor"); //foreach (Instruction i in ctor.Body.Instructions) //{ // Console.WriteLine($"offset:{i.Offset}, opcode:{i.OpCode}, operand:{i.Operand}, previous:{i.Previous}, next:{i.Next}"); //} //Console.ReadLine(); //Modifico il valore di "licenza" in "nuova licenza" ctor.Body.Instructions.SingleOrDefault(e => e.OpCode.Equals(Mono.Cecil.Cil.OpCodes.Ldstr)).Operand = "nuova licenza"; //Riscrico la dll con un nome diverso module.Write(@$ "{Directory.GetCurrentDirectory()}\..\..\..\..\Reflection.Example\bin\Debug\netcoreapp3.1\Reflection.Example.Shared-patched.dll"); module.Dispose(); //Lo copio sovrascrivendolo File.Copy(@$ "{Directory.GetCurrentDirectory()}\..\..\..\..\Reflection.Example\bin\Debug\netcoreapp3.1\Reflection.Example.Shared-patched.dll", @$ "{Directory.GetCurrentDirectory()}\..\..\..\..\Reflection.Example\bin\Debug\netcoreapp3.1\Reflection.Example.Shared.dll", true); //Cancello il file nominato diversamente File.Delete(@$ "{Directory.GetCurrentDirectory()}\..\..\..\..\Reflection.Example\bin\Debug\netcoreapp3.1\Reflection.Example.Shared-patched.dll"); result = true; } catch (Exception ex) { } return(result); }
private void Check_Click(object sender, EventArgs e) { Process[] peoplePlayground = Process.GetProcessesByName("People Playground"); if (peoplePlayground.Length == 0) { Info.Text = "People Playground not running, make sure it is running to check install."; } else { assemblyPath = peoplePlayground[0].MainModule.FileName.Replace("People Playground.exe", ""); if (MessageBox.Show($"Confirm you would like to install JFramework in {assemblyPath}?", "Confirm", MessageBoxButtons.YesNo) == DialogResult.Yes) { Info.Text = "Locating Assembly-CSharp.dll..."; if (File.Exists(assemblyPath + @"People Playground_Data\Managed\Assembly-CSharp.dll")) { Info.Text = "Assembly-CSharp.dll located, checking"; assemblyPath += @"People Playground_Data\Managed\Assembly-CSharp.dll"; AssemblyDefinition ass = AssemblyDefinition.ReadAssembly(assemblyPath); ModuleDefinition mod = ass.MainModule; if (mod.GetType("JFrameworkIdentifier") == null) { Info.Text = "JFramework is not installed"; } else { Info.Text = "JFramework is installed"; } mod.Dispose(); ass.Dispose(); } else { Info.Text = "Failed to locate Assembly-CSharp.dll, please verify the integrity of your game."; } } } }
public void Execute() { ResolveEventHandler assemblyResolve = CurrentDomain_AssemblyResolve; try { SplitUpReferences(); GetSymbolProviders(); ReadModule(); AppDomain.CurrentDomain.AssemblyResolve += assemblyResolve; InitialiseWeavers(); ExecuteWeavers(); AddWeavingInfo(); AddProcessedFlag(); FindStrongNameKey(); WriteModule(); ExecuteAfterWeavers(); DisposeWeavers(); if (weaverInstances .Any(_ => _.WeaverDelegate.AfterWeavingExecute != null)) { ReadModule(); WriteModule(); } } catch (Exception exception) { AppDomain.CurrentDomain.AssemblyResolve -= assemblyResolve; Logger.LogException(exception); } finally { ModuleDefinition?.Dispose(); SymbolStream?.Dispose(); } }
public void Execute() { ResolveEventHandler assemblyResolve = CurrentDomain_AssemblyResolve; try { SplitUpReferences(); GetSymbolProviders(); assemblyResolver = new AssemblyResolver(Logger, SplitReferences); ReadModule(); AppDomain.CurrentDomain.AssemblyResolve += assemblyResolve; TypeCache = new TypeCache(assemblyResolver.Resolve); InitialiseWeavers(); TypeCache.BuildAssembliesToScan(weaverInstances.Select(x => x.Instance)); InitialiseTypeSystem(); ExecuteWeavers(); AddWeavingInfo(); FindStrongNameKey(); WriteModule(); ModuleDefinition?.Dispose(); CleanupTempSymbolsAndAssembly(); ExecuteAfterWeavers(); DisposeWeavers(); } catch (Exception exception) { AppDomain.CurrentDomain.AssemblyResolve -= assemblyResolve; Logger.LogException(exception); } finally { ModuleDefinition?.Dispose(); CleanupTempSymbolsAndAssembly(); assemblyResolver?.Dispose(); } }
public void TearDown() { module?.Dispose(); }
public void Dispose() => _targetModule?.Dispose();
/// <summary> /// Replaces non optimized Unity operators (in target assembly) with optimized ones (from optimizations assembly) /// </summary> /// <param name="optimizationsAssemblyPath">The path to the assembly containing the optimized version of Unity's opertors</param> /// <param name="targetAssemblyPath">The path of the assembly to apply the optimizations on</param> /// <param name="deleteOptimizationsAssembly">Should the optimizations assembly be deleted after the optimization process is finished?</param> /// <param name="trimOptimizationsAssembly">Should the optimized operators be removed from the optimizations module after the optimization process is finished?</param> static public void Optimize(string optimizationsAssemblyPath, string targetAssemblyPath, bool deleteOptimizationsAssembly, bool trimOptimizationsAssembly) { const string optimizedNameSpace = "ToolBuddy.FrameRateBooster.Optimizations"; const string originalNameSpace = "UnityEngine"; ModuleDefinition optimizedModuleDefinition = ModuleDefinition.ReadModule(optimizationsAssemblyPath, new ReaderParameters() { ReadWrite = trimOptimizationsAssembly }); ModuleDefinition originalModule = ModuleDefinition.ReadModule(targetAssemblyPath, new ReaderParameters() { ReadWrite = true }); int optimizedMethods = 0; foreach (TypeDefinition optimizedType in optimizedModuleDefinition.Types) { if (optimizedType.Namespace == optimizedNameSpace) { TypeDefinition originalType = GetOriginalTypeIfAny(originalModule, originalNameSpace, optimizedType); if (originalType != null) { foreach (MethodDefinition optimizedMethod in optimizedType.Methods) { MethodDefinition method = originalType.Methods.SingleOrDefault(m => m.Name == optimizedMethod.Name && m.ReturnType.Name == optimizedMethod.ReturnType.Name && m.Parameters.Count == optimizedMethod.Parameters.Count && m.Parameters.Select(p => p.ParameterType.Name).SequenceEqual(optimizedMethod.Parameters.Select(p => p.ParameterType.Name))); if (method == null) { Debug.LogWarning(String.Format("[Frame Rate Booster] Couldn't find match for {0}.{1}", optimizedMethod.DeclaringType, optimizedMethod.Name)); continue; } method.Body.Variables.Clear(); foreach (VariableDefinition variable in optimizedMethod.Body.Variables) { if (variable.VariableType.Namespace == optimizedNameSpace) { variable.VariableType = GetOriginalType(originalModule, originalNameSpace, variable.VariableType); } method.Body.Variables.Add(variable); } method.Body.MaxStackSize = optimizedMethod.Body.MaxStackSize; method.Body.Instructions.Clear(); foreach (Instruction instruction in optimizedMethod.Body.Instructions) { Instruction newInstruction; FieldReference fieldReference = (instruction.Operand as FieldReference); MethodReference methodReference = (instruction.Operand as MethodReference); if (fieldReference != null && fieldReference.DeclaringType.Namespace == optimizedNameSpace) { newInstruction = Instruction.Create(instruction.OpCode, new FieldReference(fieldReference.Name, fieldReference.FieldType, GetOriginalType(originalModule, originalNameSpace, fieldReference.DeclaringType))); } else if (methodReference != null) { methodReference.DeclaringType = originalModule.ImportReference(methodReference.DeclaringType.Resolve()); newInstruction = instruction; } else { newInstruction = instruction; } method.Body.GetILProcessor().Append(newInstruction); optimizedMethods++; } } } } } if (optimizedMethods == 0) { Debug.LogError("[Frame Rate Booster] Couldn't find any method to optimize. This is not supposed to happen. Please report that to the asset creator."); } originalModule.Write(); if (deleteOptimizationsAssembly) { optimizedModuleDefinition.Dispose(); File.Delete(optimizationsAssemblyPath); } else if (trimOptimizationsAssembly) { List <int> indicesToRemove = new List <int>(); for (int i = 0; i < optimizedModuleDefinition.Types.Count; i++) { TypeDefinition optimizedType = optimizedModuleDefinition.Types[i]; if (optimizedType.Namespace == optimizedNameSpace) { indicesToRemove.Add(i); } } indicesToRemove.Sort(); while (indicesToRemove.Any()) { optimizedModuleDefinition.Types.RemoveAt(indicesToRemove.Last()); indicesToRemove.Remove(indicesToRemove.Last()); } //TODO assure toi que la taille de assemblyCsharp ne grandit pas optimizedModuleDefinition.Write(); } }