static void Main(string[] args) { var cli = new CommandLineApplication(); cli.ResponseFileHandling = ResponseFileHandling.ParseArgsAsLineSeparated; cli.HelpOption(); var paths = cli.Argument("paths", "The input dlls or directories of dlls to instrument", true).IsRequired(); var outputOption = cli.Option("-o|--output <DIR>", "The directory where output files will be written", CommandOptionType.SingleValue); var refPathsOption = cli.Option("-r|--reference <DIR>", "Directory to search for references", CommandOptionType.MultipleValue); var exRegexOption = cli.Option("-x|--exclude <REGEX>", "A regular expression used to exclude methods for instrumentation.", CommandOptionType.MultipleValue); var incRegexOption = cli.Option("-i|--include <REGEX>", "A regular expression used to include methods for instrumentation.", CommandOptionType.MultipleValue); cli.OnExecute(() => { var processors = new List <InstrumentationProcessor>(); var directories = new HashSet <string>(); foreach (var path in paths.Values) { if (File.Exists(path)) { if (path.EndsWith(".dll")) { processors.Add(new FileProcessor(path)); string dir = Path.GetDirectoryName(Path.GetFullPath(path)); directories.Add(dir); } else if (path.EndsWith(".zip")) { processors.Add(new ZipProcessor(path)); } } else if (Directory.Exists(path)) { processors.Add(new DirectoryProcessor(path)); directories.Add(path); } } if (processors.Count == 0) { Console.WriteLine("No assemblies found"); return; } string toolsAsmPath = LocateToolsAssembly(); var globalResolver = new DefaultAssemblyResolver(); foreach (var dir in directories) { globalResolver.AddSearchDirectory(dir); } foreach (var refPath in refPathsOption.Values) { globalResolver.AddSearchDirectory(refPath); } #if DEBUG string resolverPaths = Environment.GetEnvironmentVariable("MTGINSTR_RESOLVERPATH"); if (resolverPaths != null) { Console.WriteLine("Adding debugging assembly resolver logic"); foreach (var path in resolverPaths.Split(";")) { Console.WriteLine($"Added resolver path: {path}"); globalResolver.AddSearchDirectory(path); } } #endif var readerParams = new ReaderParameters() { AssemblyResolver = globalResolver }; var toolsAsm = AssemblyDefinition.ReadAssembly(toolsAsmPath, readerParams); string outputDirectory = Environment.CurrentDirectory; if (outputOption.HasValue()) { outputDirectory = outputOption.Value(); Console.WriteLine($"Output directory: {outputDirectory}"); } var toolsContext = new ToolsAssemblyContext(toolsAsm); var opts = new InstrumenterOptions(); opts.Excludes.AddRange(exRegexOption.Values); opts.Includes.AddRange(incRegexOption.Values); var instrumenter = new AssemblyInstrumenter(toolsContext, opts); var processingContext = new ProcessingContext() { OutputDirectory = outputDirectory, Instrumenter = instrumenter, ReaderParams = readerParams }; int success = 0; foreach (var processor in processors) { try { Console.WriteLine($"Processing {processor.DisplayName}"); processor.Process(processingContext); Console.WriteLine($"Done processing {processor.DisplayName}"); success++; } catch (Exception e) { Console.WriteLine($"Error processing {processor.DisplayName}"); Console.WriteLine($"Error details: {e}"); } } if (success > 0) { Console.WriteLine($"Successfully processed {success} items"); } }); cli.Execute(args); }
public override void Process(ProcessingContext context) { using var inputZipFs = File.OpenRead(ZipFile); using var inputArchive = new ZipArchive(inputZipFs); string outputFile = Path.Combine(context.OutputDirectory, Path.GetFileName(ZipFile)); using var outputZipFs = new FileStream(outputFile, FileMode.Create); using var outputArchive = new ZipArchive(outputZipFs, ZipArchiveMode.Create); bool isModZip = false; var metadataEntry = inputArchive.GetEntry("metadata.txt"); string primaryDll = null; if (metadataEntry != null) { isModZip = true; primaryDll = GetPrimaryDllName(metadataEntry); if (primaryDll != null) { Console.WriteLine("Appears to be a mod zip. Handling primary dll only."); } } foreach (var entry in inputArchive.Entries) { using var entryStream = entry.Open(); bool shouldProcess = entry.FullName.EndsWith(".dll"); if (isModZip && primaryDll != null) { shouldProcess = entry.Name == primaryDll; } if (shouldProcess) { // we need a seekable stream to read so we have to move the whole uncompressed file into memory. int length = checked ((int)entry.Length); using var inputMs = new MemoryStream(length); entryStream.CopyTo(inputMs); inputMs.Seek(0, SeekOrigin.Begin); using var asmDef = context.Instrumenter.InstrumentStream(inputMs, context.ReaderParams); var outputEntry = outputArchive.CreateEntry(entry.FullName); // also need a seekable stream for output... sigh using var outputMs = new MemoryStream(); asmDef.Write(outputMs); outputMs.Seek(0, SeekOrigin.Begin); using var outputStream = outputEntry.Open(); outputMs.CopyTo(outputStream); } else { var outputEntry = outputArchive.CreateEntry(entry.FullName); using var outputStream = outputEntry.Open(); entryStream.CopyTo(outputStream); } } }
public abstract void Process(ProcessingContext context);