public static int Main(string[] args) { var inputs = new List <string>(); var operation = Operation.MakeRefasm; var verbosity = LogLevel.Warning; var showHelp = false; var quiet = false; var continueOnErrors = false; var fileListAttr = new Dictionary <string, string>(); var options = new OptionSet { { "v", "increase verbosity", v => { if (v != null && verbosity > LogLevel.Trace) { verbosity--; } } }, { "q|quiet", "be quiet", v => quiet = v != null }, { "h|?|help", "show help", v => showHelp = v != null }, { "c|continue", "continue on errors", v => continueOnErrors = v != null }, { "O|outputdir=", "set output directory", v => _outputDir = v }, { "o|output=", "set output file, for single file only", v => _outputFile = v }, { "r|refasm", "make reference assembly, default action", v => { if (v != null) { operation = Operation.MakeRefasm; } } }, { "w|overwrite", "overwrite source files", v => _overwrite = v != null }, { "p|public", "drop non-public types even with InternalsVisibleTo", v => _public = v != null }, { "i|internals", "import public and internal types", v => _internals = v != null }, { "all", "ignore visibility and import all", v => _all = v != null }, { "m|mock", "make mock assembly instead of reference assembly", p => _makeMock = p != null }, { "n|noattr", "omit reference assembly attribute", p => _omitReferenceAssemblyAttr = p != null }, { "l|list", "make file list xml", v => { if (v != null) { operation = Operation.MakeXmlList; } } }, { "a|attr=", "add FileList tag attribute", v => AddFileListAttr(v, fileListAttr) }, { "g|globs", "expand globs internally: ?, *, **", p => _expandGlobs = p != null }, { "<>", "one or more input files", v => inputs.Add(v) }, }; try { options.Parse(args); } catch (InvalidOptionException e) { Console.Error.WriteLine(e.Message); return(1); } catch (Exception e) { Console.Error.WriteLine($"{e}"); return(1); } if (quiet) { verbosity = LogLevel.None; } if (showHelp || args.Length == 0) { var selfName = Path.GetFileName(Environment.GetCommandLineArgs()[0]); Console.Out.WriteLine($"Usage: {selfName} [options] <dll> [<**/*.dll> ...]"); Console.Out.WriteLine("Options:"); options.WriteOptionDescriptions(Console.Out); return(0); } if (!string.IsNullOrEmpty(_outputFile) && inputs.Count > 1) { Console.Error.WriteLine("Output file should not be specified for many inputs"); return(2); } _logger = new LoggerBase(new VerySimpleLogger(Console.Error, verbosity)); try { _logger.Trace?.Invoke($"Program arguments: {string.Join(" ", args)}"); // Apply input globbing var dirCurrent = new DirectoryInfo(Environment.CurrentDirectory); var inputsExpanded = inputs.SelectMany(input => ExpandInput(input, dirCurrent, _logger)).OrderBy(t => t.Path, StringComparer.OrdinalIgnoreCase).ToImmutableArray(); // Re-check for the second time, after expanding globs if (!string.IsNullOrEmpty(_outputFile) && inputs.Count > 1) { Console.Error.WriteLine("Output file should not be specified for many inputs"); return(2); } XmlTextWriter xmlWriter = null; if (operation == Operation.MakeXmlList) { xmlWriter = !string.IsNullOrEmpty(_outputFile) ? new XmlTextWriter(_outputFile, Encoding.UTF8) : new XmlTextWriter(Console.Out); xmlWriter.Formatting = Formatting.Indented; xmlWriter.WriteStartDocument(); xmlWriter.WriteStartElement("FileList"); foreach (var kv in fileListAttr) { xmlWriter.WriteAttributeString(kv.Key, kv.Value); } } _logger.Info?.Invoke($"Processing {inputs.Count} assemblies"); for (var nInput = 0; nInput < inputsExpanded.Length; nInput++) { var input = inputsExpanded[nInput]; _logger.Info?.Invoke($"Processing {input.Path}"); using (_logger.WithLogPrefix($"[{Path.GetFileName(input.RelativeForOutput)}]")) { try { switch (operation) { case Operation.MakeRefasm: MakeRefasm(input); break; case Operation.MakeXmlList: WriteAssemblyToXml(input, xmlWriter); break; default: throw new ArgumentOutOfRangeException(); } } catch (InvalidOperationException e) { _logger.Error?.Invoke(e.Message); if (continueOnErrors) { continue; } if (nInput < inputsExpanded.Length - 1) // When doing multiple files, let user know some might be left undone { _logger.Error?.Invoke($"Aborted on first error, {inputsExpanded.Length - nInput + 1:N0} files left unprocessed; pass “--continue” to try them anyway"); } return(1); } } } if (xmlWriter != null) { xmlWriter.WriteEndElement(); xmlWriter.WriteEndDocument(); xmlWriter.Close(); } _logger.Info?.Invoke("All done"); return(0); } catch (Exception e) { _logger.Error?.Invoke($"{e}"); _logger.Error?.Invoke("ABORTED"); // When doing multiple files, let user know some might be left undone return(1); } }
public static int Main(string[] args) { var inputs = new List <string>(); var operation = Operation.MakeRefasm; var verbosity = LogLevel.Warning; var showHelp = false; var quiet = false; var continueOnErrors = false; var fileListAttr = new Dictionary <string, string>(); var options = new OptionSet { { "v", "increase verbosity", v => { if (v != null && verbosity > LogLevel.Trace) { verbosity--; } } }, { "q|quiet", "be quiet", v => quiet = v != null }, { "h|help", "show help", v => showHelp = v != null }, { "c|continue", "continue on errors", v => continueOnErrors = v != null }, { "O|outputdir=", "set output directory", v => _outputDir = v }, { "o|output=", "set output file, for single file only", v => _outputFile = v }, { "r|refasm", "make reference assembly, default action", v => { if (v != null) { operation = Operation.MakeRefasm; } } }, { "w|overwrite", "overwrite source files", v => _overwrite = v != null }, { "l|list", "make file list xml", v => { if (v != null) { operation = Operation.MakeXmlList; } } }, { "a|attr=", "add FileList tag attribute", v => AddFileListAttr(v, fileListAttr) }, { "<>", v => inputs.Add(v) }, }; try { options.Parse(args); } catch (InvalidOptionException e) { Console.Error.WriteLine(e.Message); return(1); } catch (Exception e) { Console.Error.WriteLine($"{e}"); return(1); } if (quiet) { verbosity = LogLevel.None; } if (showHelp) { var selfName = Path.GetFileName(Environment.GetCommandLineArgs()[0]); Console.Out.WriteLine($"Usage: {selfName} [options] <dll> [<dll> ...]"); Console.Out.WriteLine("Options:"); options.WriteOptionDescriptions(Console.Out); return(0); } if (!string.IsNullOrEmpty(_outputFile) && inputs.Count > 1) { Console.Error.WriteLine("Output file should not be specified for many inputs"); return(2); } _logger = new LoggerBase(new VerySimpleLogger(Console.Error, verbosity)); try { if (!Directory.Exists(_outputDir)) { Directory.CreateDirectory(_outputDir); } _logger.Trace?.Invoke($"Program arguments: {string.Join(" ", args)}"); XmlTextWriter xmlWriter = null; if (operation == Operation.MakeXmlList) { xmlWriter = !string.IsNullOrEmpty(_outputFile) ? new XmlTextWriter(_outputFile, Encoding.UTF8) : new XmlTextWriter(Console.Out); xmlWriter.Formatting = Formatting.Indented; xmlWriter.WriteStartDocument(); xmlWriter.WriteStartElement("FileList"); foreach (var(key, value) in fileListAttr) { xmlWriter.WriteAttributeString(key, value); } inputs.Sort(); } _logger.Info?.Invoke($"Processing {inputs.Count} assemblies"); foreach (var input in inputs) { _logger.Info?.Invoke($"Processing {input}"); using (_logger.WithLogPrefix($"[{Path.GetFileName(input)}]")) { MetadataReader metaReader; PEReader peReader; try { _logger.Debug?.Invoke($"Reading assembly {input}"); peReader = new PEReader(new FileStream(input, FileMode.Open)); metaReader = peReader.GetMetadataReader(); if (!metaReader.IsAssembly) { _logger.Warning?.Invoke($"Dll has no assembly: {input}"); } } catch (InvalidOperationException e) { _logger.Error?.Invoke(e.Message); if (continueOnErrors) { continue; } return(1); } switch (operation) { case Operation.MakeRefasm: MakeRefasm(metaReader, peReader, input); break; case Operation.MakeXmlList: WriteAssemblyToXml(metaReader, xmlWriter); break; default: throw new ArgumentOutOfRangeException(); } } } if (xmlWriter != null) { xmlWriter.WriteEndElement(); xmlWriter.WriteEndDocument(); xmlWriter.Close(); } _logger.Info?.Invoke("All done"); return(0); } catch (Exception e) { _logger.Error?.Invoke($"{e}"); return(1); } }