public static bool TryReadFromAssembly(string assemblyPath, out LaunchDescriptor descriptor)
        {
            var assembly = AssemblyDefinition.ReadAssembly(assemblyPath);

            var nameAttribute          = assembly.SingleCustomAttributeOfType <Emul8.LaunchAttributes.NameAttribute>();
            var descriptionAttribute   = assembly.SingleCustomAttributeOfType <Emul8.LaunchAttributes.DescriptionAttribute>();
            var priorityAttribute      = assembly.SingleCustomAttributeOfType <PriorityAttribute>();
            var switchAttribute        = assembly.SingleCustomAttributeOfType <SwitchAttribute>();
            var configurationAttribute = assembly.SingleCustomAttributeOfType <AssemblyConfigurationAttribute>();

            if (nameAttribute == null ||
                descriptionAttribute == null ||
                priorityAttribute == null ||
                switchAttribute == null ||
                configurationAttribute == null)
            {
                descriptor = null;
                return(false);
            }

            descriptor = new LaunchDescriptor
            {
                Path                  = assemblyPath,
                Name                  = (string)nameAttribute.ConstructorArguments[0].Value,
                Description           = (string)descriptionAttribute.ConstructorArguments[0].Value,
                Priority              = (uint)priorityAttribute.ConstructorArguments[0].Value,
                ShortSwitch           = switchAttribute.ConstructorArguments.Count == 2 ? (char?)switchAttribute.ConstructorArguments[1].Value : null,
                LongSwitch            = (string)switchAttribute.ConstructorArguments[0].Value,
                ProvidesHelp          = assembly.SingleCustomAttributeOfType <ProvidesHelpAttribute>() != null,
                AssemblyConfiguration = (Configuration)Enum.Parse(typeof(Configuration), (string)configurationAttribute.ConstructorArguments[0].Value)
            };
            return(true);
        }
Beispiel #2
0
        public static IEnumerable <LaunchDescriptorsGroup> ScanForInterestingBinaries(string directory)
        {
            var descriptors = new List <LaunchDescriptor>();

            foreach (var file in Directory.GetFiles(directory, "*.exe", SearchOption.AllDirectories))
            {
                LaunchDescriptor descriptor;
                if (LaunchDescriptor.TryReadFromAssembly(file, out descriptor))
                {
                    descriptors.Add(descriptor);
                }
            }

            var result = new List <LaunchDescriptorsGroup>();
            var groups = descriptors.GroupBy(x => new { x.Name, x.Description, x.Priority, x.ShortSwitch, x.LongSwitch, x.ProvidesHelp });

            foreach (var group in groups)
            {
                result.Add(new LaunchDescriptorsGroup(group.ToArray()));
            }

            return(result);
        }
Beispiel #3
0
        public static void Main(string[] args)
        {
            var basicOptions  = new BasicOptions();
            var optionsParser = new OptionsParser(new ParserConfiguration
            {
                GenerateHelp             = false,
                AllowUnexpectedArguments = true
            });

            // here we parse only one option - `root-directory`
            // the rest will be parsed in the second phase
            if (!optionsParser.Parse(basicOptions, args))
            {
                return;
            }

            optionsParser = new OptionsParser(new ParserConfiguration
            {
                GenerateHelp             = true,
                CustomFooterGenerator    = () => "All unparsed options will be forwarded to launched application.",
                CustomUsageLineGenerator = usageLine => usageLine + " [script]",
                AllowUnexpectedArguments = true
            });

            var addHelpSwitch     = false;
            var possibleLaunchees = new List <LaunchDescriptorsGroup>();
            var selectedLaunchees = new List <LaunchDescriptorsGroup>();

            var interestingBinaries = Scanner.ScanForInterestingBinaries(basicOptions.RootPath).OrderBy(x => x.Priority).ThenBy(x => x.Name).ToArray();

            for (var i = 0; i < interestingBinaries.Length; i++)
            {
                var j = i;
                possibleLaunchees.Add(interestingBinaries[i]);
                interestingBinaries[i].GenerateSwitches(optionsParser, i == 0);
                interestingBinaries[i].SwitchOption.Parsed += (option, value) =>
                {
                    selectedLaunchees.Add(interestingBinaries[j]);
                };

                if (interestingBinaries[i].HelpOption != null)
                {
                    interestingBinaries[i].HelpOption.Parsed += (option, value) =>
                    {
                        addHelpSwitch = true;
                    };
                }
            }

            // here we parse all of the options again
            // as only now we know which launch targets
            // and configurations are available in the
            // system
            var options = new Options();

            if (!optionsParser.Parse(options, args))
            {
                return;
            }

            var conf = options.Debug ? LaunchDescriptor.Configuration.Debug : LaunchDescriptor.Configuration.Release;
            LaunchDescriptorsGroup selectedGroup    = null;
            LaunchDescriptor       selectedLaunchee = null;

            if (selectedLaunchees.Count == 0)
            {
                if (possibleLaunchees.Count == 0)
                {
                    Console.Error.WriteLine("There is no launch target specified. Exiting");
                    Environment.Exit(1);
                }

                selectedGroup = possibleLaunchees.OrderBy(x => x.Priority).ThenBy(x => x.Name).First();
            }
            else if (selectedLaunchees.Count > 1)
            {
                Console.Error.WriteLine("Only one launch target can be used. Exiting");
                Environment.Exit(1);
            }
            else
            {
                selectedGroup = selectedLaunchees.First();
            }

            selectedLaunchee = selectedGroup.ForConfiguration(conf);
            if (selectedLaunchee == null)
            {
                Console.Error.WriteLine("Selected target {0} is not available in {1} configuration.", selectedGroup.Name, conf);
                Environment.Exit(1);
            }

#if !PLATFORM_WINDOWS
            // it is not so easy to remotely debug on .NET, so we do not support it
            var monoOptions = options.Debug ? "--debug" : string.Empty;

            if (options.DebuggerSocketPort != -1)
            {
                monoOptions += string.Format(" --debugger-agent=transport=dt_socket,address=127.0.0.1:{0},server=y", options.DebuggerSocketPort);
                Console.WriteLine("Listening on port {0}", options.DebuggerSocketPort);
            }
#endif

            var optionsToPass = optionsParser.RecreateUnparsedArguments();
            if (addHelpSwitch)
            {
                Console.WriteLine("NOTE: showing help from binary: {0}", selectedLaunchee.Name);
                optionsToPass = "******";
            }

            var process = new Process();
#if PLATFORM_WINDOWS
            process.StartInfo.FileName  = selectedLaunchee.Path;
            process.StartInfo.Arguments = optionsToPass;
#else
            process.StartInfo.FileName  = "mono";
            process.StartInfo.Arguments = string.Format("{0} {1} {2}", monoOptions, selectedLaunchee.Path, optionsToPass);
#endif

            if (options.Quiet)
            {
                process.StartInfo.RedirectStandardError = true;
                process.StartInfo.UseShellExecute       = false;
            }

            process.Start();
            if (options.Quiet)
            {
                process.StandardError.Close();
            }

            process.WaitForExit();
        }