Exemplo n.º 1
0
        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);
            }
        }
Exemplo n.º 2
0
        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);
            }
        }