public RemapContext(ModuleDefMD module, ModuleDefMD targetModule, HashSet <string> sourceAssemblies, RemapOptions options) { this.Module = module; this.TargetModule = targetModule; this.SourceAssemblies = sourceAssemblies; this.Options = options; }
static int Main(string[] args) { var app = new CommandLineApplication(); app.HelpOption("-?|--help"); var assemblyArgument = app.Argument("assembly", "The path to the assembly to be edited."); var sourceOption = app.Option("-s|--source", "Source assembly name to be remapped.", CommandOptionType.MultipleValue); var targetOption = app.Option("-t|--target", "Target assembly path.", CommandOptionType.SingleValue); var outputOption = app.Option("-o|--output", "Output path where the generated assembly will be written to.", CommandOptionType.SingleValue); var resolveOption = app.Option("-r|--resolve", "Attempt to resolve types after remapping.", CommandOptionType.NoValue); app.OnExecute(async() => { var logger = new ConsoleLogger(); if (string.IsNullOrEmpty(assemblyArgument.Value)) { await logger.Log(LogLevel.Error, "No assembly specified."); return(1); } if (!sourceOption.HasValue()) { await logger.Log(LogLevel.Error, "No source assembly names specified."); return(1); } if (!targetOption.HasValue()) { await logger.Log(LogLevel.Error, "No target assembly specified."); return(1); } if (!outputOption.HasValue()) { await logger.Log(LogLevel.Error, "No output path specified."); return(1); } var assemblyPath = Path.GetFullPath(assemblyArgument.Value); if (!File.Exists(assemblyPath)) { await logger.Log(LogLevel.Error, "Input assembly not found."); return(1); } var targetAssemblyPath = Path.GetFullPath(targetOption.Value()); if (!File.Exists(targetAssemblyPath)) { await logger.Log(LogLevel.Error, "Target assembly not found."); return(1); } var outputPath = Path.GetFullPath(outputOption.Value()); if (!Directory.Exists(Path.GetDirectoryName(outputPath))) { Directory.CreateDirectory(Path.GetDirectoryName(outputPath)); } var remapOptions = new RemapOptions(); if (resolveOption.HasValue()) { remapOptions.Resolve = true; } var remapper = new Remapper(logger, assemblyPath, sourceOption.Values); return(await remapper.Remap(targetAssemblyPath, outputPath, remapOptions)); }); return(app.Execute(args)); }
public async Task <int> Remap(string targetAssemblyPath, string outputPath, RemapOptions options) { await logger.Log(LogLevel.Info, $"Processing \'{assemblyPath}\'..."); var targetName = Path.GetFileNameWithoutExtension(targetAssemblyPath); var contextSourceNames = new HashSet <string>(sourceNames); if (contextSourceNames.Contains(targetName)) { contextSourceNames.Remove(targetName); } var assemblyResolver = new AssemblyResolver(); var moduleContext = new ModuleContext(assemblyResolver); assemblyResolver.DefaultModuleContext = moduleContext; assemblyResolver.EnableTypeDefCache = true; using (var module = ModuleDefMD.Load(assemblyPath)) { module.Context = moduleContext; assemblyResolver.AddToCache(module); using (var targetModule = ModuleDefMD.Load(targetAssemblyPath)) { targetModule.Context = moduleContext; // The target module is never modified, so this is safe to enable targetModule.EnableTypeDefFindCache = true; assemblyResolver.AddToCache(targetModule); var remapContext = new RemapContext(module, targetModule, contextSourceNames, options); var remappers = new List <IRemapper>() { new ILRemapper(remapContext), new WPFRemapper(remapContext) }; foreach (var remapper in remappers) { if (remapper.IsCompatible()) { remapper.Remap(); } } module.Write(outputPath); } } // NOTE: References are only updated after the new module has been written using (var module = ModuleDefMD.Load(outputPath)) { var references = module.GetAssemblyRefs(); if (references.Where(x => contextSourceNames.Contains(x.Name)).Any()) { await logger.Log(LogLevel.Error, "Remap completed with errors. Some portions were not remapped."); return(1); } } await logger.Log(LogLevel.Info, $"Remap completed for \'{assemblyPath}\'."); return(0); }