/// <summary>
        /// Sets CommandLineFailure field if there is a parse failure
        /// </summary>
        public void ParseArgs(string[] args)
        {
            try
            {
                var parser = new CommandLineParser(args);
                SetupCommandLine(parser);
                if (parser.HelpRequested != null)
                {
                    HelpRequested = true;
                }

                if (CommandAndArgs != null)
                {
                    CommandLine = CommandLineUtilities.FormCommandLineFromArguments(CommandAndArgs, 0);
                }

                parser.CompleteValidation();
            }
            catch (CommandLineParserException e)
            {
                CommandLineFailure = e;
            }
        }
Example #2
0
        /// <summary>
        /// Sends the telemetry with the suggestion returned to the user.
        /// </summary>
        private void SendTelemetry(GetSuggestionTelemetryData telemetryData)
        {
            var suggestions      = telemetryData.Suggestion?.PredictiveSuggestions;
            var suggestionSource = telemetryData.Suggestion?.SuggestionSources;
            var sourceTexts      = telemetryData.Suggestion?.SourceTexts;
            var maskedUserInput  = CommandLineUtilities.MaskCommandLine(telemetryData.UserInput?.FindAll((ast) => ast is CommandAst, true).LastOrDefault() as CommandAst);

            if ((suggestions != null) && (sourceTexts != null))
            {
                for (int i = 0; i < suggestions.Count; ++i)
                {
                    _userAcceptedAndSuggestion[suggestions[i].SuggestionText] = sourceTexts[i];
                }
            }

            var properties = CreateProperties(telemetryData);

            properties.Add("UserInput", maskedUserInput ?? string.Empty);
            properties.Add("Suggestion", sourceTexts != null ? JsonSerializer.Serialize(sourceTexts.Zip(suggestionSource).Select((s) => Tuple.Create(s.First, s.Second)), JsonUtilities.TelemetrySerializerOptions) : string.Empty);
            properties.Add("IsCancelled", telemetryData.IsCancellationRequested.ToString(CultureInfo.InvariantCulture));
            properties.Add("Exception", telemetryData.Exception?.ToString() ?? string.Empty);

            _telemetryClient.TrackEvent($"{AzPredictorTelemetryClient.TelemetryEventPrefix}/GetSuggestion", properties);
        }
        public void SingletonPathOption()
        {
            CommandLineUtilities.Option opt = default(CommandLineUtilities.Option);

            opt.Name  = "Switch";
            opt.Value = "test.dll";
            Assert.Equal(Path.Combine(Directory.GetCurrentDirectory(), "test.dll"), CommandLineUtilities.ParseSingletonPathOption(opt, null));

            if (!OperatingSystemHelper.IsUnixOS)
            {
                opt.Name  = "Switch";
                opt.Value = SpecialFolderUtilities.GetFolderPath(SpecialFolder.Windows);
                Assert.Equal(opt.Value, CommandLineUtilities.ParseSingletonPathOption(opt, null));
            }

            Assert.Throws <InvalidArgumentException>(() =>
            {
                opt.Name  = "Switch";
                opt.Value = null;
                CommandLineUtilities.ParseSingletonPathOption(opt, null);
            });

            Assert.Throws <InvalidArgumentException>(() =>
            {
                opt.Name  = "Switch";
                opt.Value = string.Empty;
                CommandLineUtilities.ParseSingletonPathOption(opt, null);
            });

            Assert.Throws <InvalidArgumentException>(() =>
            {
                opt.Name  = "Switch";
                opt.Value = "New";
                CommandLineUtilities.ParseSingletonPathOption(opt, "Existing");
            });
        }
        private static void CommonCommandLineTests(CommandLineUtilities clu)
        {
            CommandLineUtilities.Option[] opts = clu.Options.ToArray();
            string[] argStrings = clu.Arguments.ToArray();

            Assert.Equal(4, opts.Length);
            Assert.Equal(3, argStrings.Length);

            Assert.Equal("opt0", opts[0].Name);
            Assert.True(string.IsNullOrEmpty(opts[0].Value));

            Assert.Equal("opt1", opts[1].Name);
            Assert.True(string.IsNullOrEmpty(opts[1].Value));

            Assert.Equal("opt2", opts[2].Name);
            Assert.Equal("abc", opts[2].Value);

            Assert.Equal("opt3", opts[3].Name);
            Assert.Equal("abc xyz", opts[3].Value);

            Assert.Equal("Arg0", argStrings[0]);
            Assert.Equal("Arg1", argStrings[1]);
            Assert.Equal("Arg2a Arg2b", argStrings[2]);
        }
        /// <summary>
        /// executes the command-line workflow
        /// </summary>
        public void Execute(string[] args)
        {
            var bench = new Benchmark();

            try
            {
                List <string> unsupportedOps = null;

                if (args == null || args.Length == 0)
                {
                    SetExitCode(ExitCodes.MissingCommandLineOption);
                    _showHelpMenu = true;
                }
                else
                {
                    try
                    {
                        unsupportedOps = _commandLineOps.Parse(args);

                        if (unsupportedOps.Count > 0)
                        {
                            SetExitCode(ExitCodes.UnknownCommandLineOption);
                            _showHelpMenu = true;
                        }
                    }
                    catch (OptionException oe)
                    {
                        _errorBuilder.AppendFormat("{0}ERROR: {1}\n", _errorSpacer, oe.Message);
                        SetExitCode(ExitCodes.UnknownCommandLineOption);
                        _showHelpMenu = true;
                    }
                }

                if (_showVersion)
                {
                    Console.WriteLine("{0} {1}", _versionProvider.GetProgramVersion(), _versionProvider.GetDataVersion());
                    SetExitCode(ExitCodes.Success);
                }
                else
                {
                    if (!Console.IsOutputRedirected)
                    {
                        CommandLineUtilities.DisplayBanner(_programAuthors);
                    }

                    if (_showHelpMenu)
                    {
                        Help.Show(_commandLineOps, _commandLineExample, _programDescription);

                        CommandLineUtilities.ShowUnsupportedOptions(unsupportedOps);

                        Console.WriteLine();
                        Console.WriteLine(_versionProvider.GetDataVersion());
                        Console.WriteLine();

                        // print the errors if any were found
                        if (FoundParsingErrors())
                        {
                            return;
                        }
                    }
                    else
                    {
                        ValidateCommandLine();

                        // print the errors if any were found
                        if (FoundParsingErrors())
                        {
                            return;
                        }

                        ProgramExecution();
                    }
                }
            }
            catch (Exception e)
            {
                ExitCode = ExitCodeUtilities.ShowException(e);
            }

            _peakMemoryUsageBytes = MemoryUtilities.GetPeakMemoryUsage();
            _wallTimeSpan         = bench.GetElapsedTime();

            if (!_showVersion && !_showHelpMenu && !Console.IsOutputRedirected)
            {
                Console.WriteLine();
                if (_peakMemoryUsageBytes > 0)
                {
                    Console.WriteLine("Peak memory usage: {0}", MemoryUtilities.ToHumanReadable(_peakMemoryUsageBytes));
                }
                Console.WriteLine("Time: {0}", Benchmark.ToHumanReadable(_wallTimeSpan));
            }
        }
        public DumpPipAnalyzer(AnalysisInput input, string outputFilePath, long semiStableHash, DirectoryArtifact directory, bool useOriginalPaths, bool logProgress = false)
            : base(input)
        {
            if (string.IsNullOrEmpty(outputFilePath))
            {
                outputFilePath = Path.Combine(Path.GetDirectoryName(input.ExecutionLogPath), $"Pip{semiStableHash:X16}.html");
                Console.WriteLine($"Missing option /outputFilePath using: {outputFilePath}");
            }

            m_outputFilePath   = outputFilePath;
            m_useOriginalPaths = useOriginalPaths;

            if (logProgress)
            {
                Console.WriteLine("Finding matching pip");
            }

            var pipTable = input.CachedGraph.PipTable;

            foreach (var pipId in pipTable.StableKeys)
            {
                if (pipTable.GetPipType(pipId) == PipType.Module)
                {
                    var modulePip = (ModulePip)pipTable.HydratePip(pipId, PipQueryContext.ViewerAnalyzer);
                    m_moduleIdToFriendlyName.Add(modulePip.Module, modulePip.Identity.ToString(StringTable));
                }

                var possibleMatch = pipTable.GetPipSemiStableHash(pipId);
                if (possibleMatch == semiStableHash)
                {
                    m_pip = pipTable.HydratePip(pipId, PipQueryContext.ViewerAnalyzer);
                }
            }

            if (directory.IsValid)
            {
                Console.WriteLine("Looking for a pip that produced the specified DirectoryArtifact.");

                var directoryProducers = input.CachedGraph.PipGraph.AllOutputDirectoriesAndProducers.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
                if (directoryProducers.TryGetValue(directory, out var pipId))
                {
                    m_pip = pipTable.HydratePip(pipId, PipQueryContext.ViewerAnalyzer);
                }
                // This directory artifact does not have a registered producer. This might happen if it represents a composite SOD.
                else if (directory.IsSharedOpaque)
                {
                    directoryProducers = input.CachedGraph.PipGraph.AllCompositeSharedOpaqueDirectoriesAndProducers.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
                    if (directoryProducers.TryGetValue(directory, out pipId))
                    {
                        m_pip = pipTable.HydratePip(pipId, PipQueryContext.ViewerAnalyzer);
                    }
                }
            }

            if (m_pip == null)
            {
                throw CommandLineUtilities.Error("Did not find a matching pip.");
            }

            m_html = new HtmlHelper(PathTable, StringTable, SymbolTable, CachedGraph.PipTable);
        }
        public ParameterSet(CommandAst commandAst)
        {
            Validation.CheckArgument(commandAst, $"{nameof(commandAst)} cannot be null.");

            var parameters            = new List <Parameter>();
            var elements              = commandAst.CommandElements.Skip(1);
            CommandParameterAst param = null;
            Ast arg = null;

            foreach (Ast elem in elements)
            {
                if (elem is CommandParameterAst p)
                {
                    AddParameter(param, arg);
                    param = p;
                    arg   = null;
                }
                else if (AzPredictorConstants.ParameterIndicator == elem?.ToString().Trim().FirstOrDefault())
                {
                    // We have an incomplete command line such as
                    // `New-AzResourceGroup -Name ResourceGroup01 -Location WestUS -`
                    // We'll ignore the incomplete parameter.
                    AddParameter(param, arg);
                    param = null;
                    arg   = null;
                }
                else
                {
                    arg = elem;
                }
            }

            Validation.CheckInvariant((param != null) || (arg == null));

            AddParameter(param, arg);

            Parameters = parameters;

            void AddParameter(CommandParameterAst parameterName, Ast parameterValue)
            {
                if (parameterName != null)
                {
                    parameters.Add(new Parameter(parameterName.ParameterName, (parameterValue == null) ? null : CommandLineUtilities.UnescapePredictionText(parameterValue.ToString())));
                }
            }
        }
Example #8
0
        static void SafeMain(string[] args)
        {
            int    count = 1;
            string t;
            var    etwProvider = CommandLineUtilities.GetArgument("etw", Guid.Empty);

            Console.WriteLine("TraceSpy Test.");
            Console.WriteLine();
            Console.WriteLine("Press Q (or CTRL-C) to quit");
            Console.WriteLine();
            Console.WriteLine("OutputDebugString");
            Console.WriteLine(" Press O to send an OutputDebugString trace.");

            if (etwProvider != Guid.Empty)
            {
                _etw = new EventProvider(etwProvider);
                Console.WriteLine();
                Console.WriteLine("ETW");
                Console.WriteLine(" Press E to send an ETW trace to provider '" + etwProvider + "'.");
                Console.WriteLine(" Press 1..9 to send 0..9 ETW traces to provider '" + etwProvider + "'.");
                Console.WriteLine("  Combine with Shift to multiply by 10");
                Console.WriteLine("  Combine with Control to multiply by 100");
                Console.WriteLine("  Combine with Alt to multiply by 1000");
            }

            Console.WriteLine();
            do
            {
                var info = Console.ReadKey(true);
                int key  = (int)info.Key;
                int num  = GetFinalNumber(info);
                switch (info.Key)
                {
                case ConsoleKey.Q:
                    if (_etw != null)
                    {
                        _etw.Dispose();
                    }
                    return;

                case ConsoleKey.O:
                    t = "Trace #" + count + " from TraceSpyTest. Date:" + DateTime.Now;
                    Console.WriteLine("Sending: '" + t + "'");
                    Trace.WriteLine(t);
                    count++;
                    break;

                case ConsoleKey.E:
                    t = "Trace #" + count + " from TraceSpyTest. Date:" + DateTime.Now;
                    Console.WriteLine("Sending: '" + t + "'");
                    _etw.WriteMessageEvent(t);
                    count++;
                    break;

                default:
                    if (num > 0)
                    {
                        for (int i = 1; i <= num; i++)
                        {
                            t = "Trace #" + count + ", " + i + "/" + num + " from TraceSpyTest. Date:" + DateTime.Now;
                            Console.WriteLine("Sending: '" + t + "'");
                            _etw.WriteMessageEvent(t);
                            count++;
                        }
                    }
                    break;
                }
            }while (true);
        }
Example #9
0
 public static IEnumerable <string> SplitCommandLineIntoArguments(string commandLine, bool removeHashComments)
 {
     return(CommandLineUtilities.SplitCommandLineIntoArguments(commandLine, removeHashComments));
 }
Example #10
0
        /// <inhericdoc />
        public void StartEarlyProcessing(IReadOnlyList <string> history)
        {
            // The context only changes when the user executes the corresponding command.
            _azContext?.UpdateContext();

            if (history.Count > 0)
            {
                // We try to find the commands to request predictions for.
                // We should only have "start_of_snippet" when there are no enough Az commands for prediction.
                // We then ignore that when there are new "start_of_snippet".
                // This is the scenario.
                // 1. New-AzResourceGroup -Name ****
                // 2. $resourceName="Test"
                // 3. $resourceLocation="westus2"
                // 4. New-AzVM -Name $resourceName -Location $resourceLocation
                //
                // We'll replace 2 and 3 with "start_of_snippet" but if we request prediction using 2 and 3, that'll reset the
                // workflow. We want to predict only by Az commands. That's to use commands 1 and 4.

                bool isLastTwoCommandsChanged = false;

                if (_lastTwoMaskedCommands.Count == 0)
                {
                    // This is the first time we populate our record. Push the second to last command in history to the
                    // queue. If there is only one command in history, push the command placeholder.

                    if (history.Count() > 1)
                    {
                        string secondToLastLine    = history.TakeLast(AzPredictorConstants.CommandHistoryCountToProcess).First();
                        var    secondToLastCommand = GetAstAndMaskedCommandLine(secondToLastLine);
                        _lastTwoMaskedCommands.Enqueue(secondToLastCommand.Item2);

                        if (!string.Equals(AzPredictorConstants.CommandPlaceholder, secondToLastCommand.Item2, StringComparison.Ordinal))
                        {
                            _service.RecordHistory(secondToLastCommand.Item1);
                        }
                    }
                    else
                    {
                        _lastTwoMaskedCommands.Enqueue(AzPredictorConstants.CommandPlaceholder);
                        // We only extract parameter values from the command line in _service.RecordHistory.
                        // So we don't need to do that for a placeholder.
                    }

                    isLastTwoCommandsChanged = true;
                }

                string lastLine               = history.Last();
                var    lastCommand            = GetAstAndMaskedCommandLine(lastLine);
                bool   isLastCommandSupported = !string.Equals(AzPredictorConstants.CommandPlaceholder, lastCommand.Item2, StringComparison.Ordinal);

                if (isLastCommandSupported)
                {
                    if (_lastTwoMaskedCommands.Count == 2)
                    {
                        // There are already two commands, dequeue the oldest one.
                        _lastTwoMaskedCommands.Dequeue();
                    }

                    _lastTwoMaskedCommands.Enqueue(lastCommand.Item2);
                    isLastTwoCommandsChanged = true;

                    _service.RecordHistory(lastCommand.Item1);
                }
                else if (_lastTwoMaskedCommands.Count == 1)
                {
                    isLastTwoCommandsChanged = true;
                    var existingInQueue = _lastTwoMaskedCommands.Dequeue();
                    _lastTwoMaskedCommands.Enqueue(AzPredictorConstants.CommandPlaceholder);
                    _lastTwoMaskedCommands.Enqueue(existingInQueue);
                }

                _telemetryClient.OnHistory(new HistoryTelemetryData(lastCommand.Item2));

                if (isLastTwoCommandsChanged)
                {
                    _service.RequestPredictions(_lastTwoMaskedCommands);
                }
            }

            ValueTuple <CommandAst, string> GetAstAndMaskedCommandLine(string commandLine)
            {
                var    asts              = Parser.ParseInput(commandLine, out _, out _);
                var    allNestedAsts     = asts?.FindAll((ast) => ast is CommandAst, true);
                var    commandAst        = allNestedAsts?.LastOrDefault() as CommandAst;
                string maskedCommandLine = AzPredictorConstants.CommandPlaceholder;

                var commandName = commandAst?.CommandElements?.FirstOrDefault().ToString();

                if (_service.IsSupportedCommand(commandName))
                {
                    maskedCommandLine = CommandLineUtilities.MaskCommandLine(commandAst);
                }

                return(ValueTuple.Create(commandAst, maskedCommandLine));
            }
        }
        public void tuple_command_shall_be_parsed_properly_in_different_scenarios(string cmd, string[] expected)
        {
            var results = CommandLineUtilities.SplitCommandLine(cmd).ToArray();

            results.ShouldBe(expected);
        }
Example #12
0
        public void VerifyUnescapingText(string expected, string input)
        {
            var actual = CommandLineUtilities.UnescapePredictionText(input);

            Assert.Equal(expected, actual);
        }
        public void PathOption()
        {
            CommandLineUtilities.Option opt = default(CommandLineUtilities.Option);

            opt.Name  = "Switch";
            opt.Value = "test.dll";
            Assert.Equal(Path.Combine(Directory.GetCurrentDirectory(), "test.dll"), CommandLineUtilities.ParsePathOption(opt));

            // Paths may be wrapped in quotes
            opt.Value = "\"File With Spaces.dll\"";
            Assert.Equal(Path.Combine(Directory.GetCurrentDirectory(), "File With Spaces.dll"), CommandLineUtilities.ParsePathOption(opt));

            if (!OperatingSystemHelper.IsUnixOS)
            {
                opt.Name  = "Switch";
                opt.Value = SpecialFolderUtilities.GetFolderPath(SpecialFolder.Windows);
                Assert.Equal(opt.Value, CommandLineUtilities.ParsePathOption(opt));
            }

            Assert.Throws <InvalidArgumentException>(() =>
            {
                opt.Name  = "Switch";
                opt.Value = null;
                CommandLineUtilities.ParsePathOption(opt);
            });

            Assert.Throws <InvalidArgumentException>(() =>
            {
                opt.Name  = "Switch";
                opt.Value = string.Empty;
                CommandLineUtilities.ParsePathOption(opt);
            });
        }
        static void Main()
        {
            _projectPath                    = CommandLineUtilities.GetArgument("path", (string)null) ?? CommandLineUtilities.GetArgument(0, (string)null);
            _schema                         = ConvertUtilities.Nullify(CommandLineUtilities.GetArgument("schema", (string)null) ?? CommandLineUtilities.GetArgument(1, (string)null), true);
            _changeTargetDirectory          = CommandLineUtilities.GetArgument("changeTargetDirectory", true);
            _disableNonPersistenceProducers = CommandLineUtilities.GetArgument("disableNonPersistenceProducers", true);

            // Load the model
            Project project = new Project();

            project.Entities.ListChanged += Entities_ListChanged; // Change schema as soon as the entity is loaded
            project.Load(_projectPath, ProjectLoadOptions.Default);

            // Update producer target directory
            if (!string.IsNullOrEmpty(_schema) && _changeTargetDirectory)
            {
                foreach (var producer in project.Producers)
                {
                    var sqlServerProducer = producer.Instance as SqlServerProducer;
                    if (sqlServerProducer != null)
                    {
                        sqlServerProducer.Production += SqlServerProducer_Production;
                    }

                    var databaseProducer = producer.Instance as DatabaseProducer;
                    if (databaseProducer != null)
                    {
                        databaseProducer.Production += DatabaseProducer_Production;
                    }
                }
            }

            // Generate code
            project.Producing += OnProjectProduction;
            ProductionOptions productionOptions = BuildProductionOptions(project);

            project.Produce(productionOptions);
            Console.WriteLine();
        }
        private static ProductionOptions BuildProductionOptions(Project project)
        {
            ProductionOptions options = _disableNonPersistenceProducers ? new DatabaseProducerOnlyProductionOptions() : new ProductionOptions();

            options.Flags = CommandLineUtilities.GetArgument("opf", ProductionOptionsFlags.None);

            foreach (KeyValuePair <string, bool> kvp in new NameValueCollectionCollection(CommandLineUtilities.GetArgument <string>("ena", null),
                                                                                          '!', '"', '=', true, true, false, false
                                                                                          ).ToDictionary <bool>())
            {
                Producer producer = project.GetProducer(kvp.Key);
                if (producer != null)
                {
                    options.Enable(producer, kvp.Value);
                }
                else
                {
                    CodeFluent.Model.SubProducer sp = project.GetSubProducer(kvp.Key);
                    if (sp != null)
                    {
                        options.Enable(sp, kvp.Value);
                    }
                    else
                    {
                        Guid guid = ConvertUtilities.ChangeType(kvp.Key, Guid.Empty);
                        if (guid != Guid.Empty)
                        {
                            Node node = project.GetNode(guid);
                            if (node != null)
                            {
                                options.Enable(node, kvp.Value);
                            }
                        }
                    }
                }
            }
            return(options);
        }
Example #16
0
    /// <summary>
    /// This program generates C# code for manipulating ETW events given the event XML schema definition
    /// </summary>
    /// <param name="args"></param>
    public static int Main(string[] args)
    {
        return(CommandLineUtilities.RunConsoleMainWithExceptionProcessing(delegate
        {
            // See code:#CommandLineDefinitions for command line definitions
            CommandLine commandLine = new CommandLine();
#if PRIVATE
            if (commandLine.Mof)
            {
                string mofFile = commandLine.ManifestFile;
                commandLine.ManifestFile = Path.ChangeExtension(mofFile, ".man.xml");
                Console.WriteLine("Converting " + mofFile + " to the manifest " + commandLine.ManifestFile);
                CreateManifestFromMof(mofFile, commandLine.ManifestFile, commandLine.Verbose);
            }
#endif

            if (commandLine.EventSource != null)
            {
                string exe = commandLine.ManifestFile;
                var eventSources = EventSourceFinder.GetEventSourcesInFile(exe, true);
                bool foundEventSource = false;

                foreach (var eventSource in eventSources)
                {
                    var name = EventSourceFinder.GetName(eventSource);
                    Console.WriteLine("Found EventSource {0} in {1}", name, exe);
                    if (commandLine.EventSource.Length == 0 || string.Compare(name, commandLine.EventSource, StringComparison.OrdinalIgnoreCase) == 0)
                    {
                        commandLine.ManifestFile = Path.ChangeExtension(commandLine.OutputFile, ".manifest.xml");
                        Console.WriteLine("Generated manifest from EventSource {0}", name);
                        File.WriteAllText(commandLine.ManifestFile, EventSourceFinder.GetManifest(eventSource));
                        foundEventSource = true;
                        break;
                    }
                }
                if (!foundEventSource)
                {
                    throw new ApplicationException("Could not find an eventSource named " + commandLine.EventSource + " in " + exe);
                }
            }

            Console.WriteLine("Reading manifest file " + commandLine.ManifestFile);
#if PRIVATE
#if MERGE
            if (commandLine.Merge)
            {
                bool shouldMerge = File.Exists(commandLine.OutputFile) && File.Exists(commandLine.BaseFile);
                string newBaseLine = commandLine.BaseFile + ".new";
                string newOutput = commandLine.OutputFile + ".new";
                schema.CreateParserSource(newBaseLine);
                Console.WriteLine("Writing output to " + newBaseLine);
                ApplyRenames(commandLine.RenameFile, newBaseLine);

                if (shouldMerge)
                {
                    string cmd = "vssmerge -M \"" +
                                 commandLine.BaseFile + "\" \"" +
                                 newBaseLine + "\" \"" +
                                 commandLine.OutputFile + "\" \"" +
                                 newOutput + "\"";

                    Console.WriteLine("Running: " + cmd);
                    Command command = Command.Run(cmd, new CommandOptions().AddTimeout(CommandOptions.Infinite).AddNoThrow());
                    if (command.ExitCode == 0 && File.Exists(newOutput))
                    {
                        Console.WriteLine("Success, updating output and baseline file (old files in *.orig)");
                        FileUtilities.ForceCopy(commandLine.OutputFile, commandLine.OutputFile + ".orig");
                        FileUtilities.ForceCopy(commandLine.BaseFile, commandLine.BaseFile + ".orig");
                        FileUtilities.ForceMove(newOutput, commandLine.OutputFile);
                        FileUtilities.ForceMove(newBaseLine, commandLine.BaseFile);
                    }
                    else
                    {
                        Console.WriteLine("Error running merge command, doing nothing.");
                        return 1;
                    }
                }
                else
                {
                    FileUtilities.ForceMove(newBaseLine, commandLine.OutputFile);
                    FileUtilities.ForceMove(newBaseLine, commandLine.BaseFile);
                }
            }
            else
#endif //  MERGE
            {
                if (File.Exists(commandLine.BaseFile))
                {
                    throw new ApplicationException("Baseline file " + commandLine.BaseFile + " exists.  Did you mean to merge?");
                }

                Console.WriteLine("Writing output to " + commandLine.OutputFile);
                schema.CreateParserSource(commandLine.OutputFile);
            }
#endif // PRIVATE
            List <ETWManifest.Provider> providers = ETWManifest.Provider.ParseManifest(commandLine.ManifestFile);
            foreach (var provider in providers)
            {
                var parserGen = new TraceParserGen(provider);
                parserGen.Internal = commandLine.Internal;
                parserGen.NeedsParserState = commandLine.NeedsState;

                Console.WriteLine("Writing output to " + commandLine.OutputFile);
                parserGen.GenerateTraceEventParserFile(commandLine.OutputFile);
                break;  // TODO FIX NOW allow multiple providers in a manifest.
            }
#if PRIVATE
            ApplyRenames(commandLine.RenameFile, commandLine.OutputFile);
#endif
            return 0;
        }));
    }
Example #17
0
        /// <summary>
        /// Attempts to parse the configuration. This is a subset of what's parsed in Args
        /// </summary>
        /// <remarks>
        /// Keep the subset of parsing here limited to whatever's needed to run the client process
        /// </remarks>
        public static bool TryParse(string[] args, out LightConfig lightConfig)
        {
            lightConfig = new LightConfig();

            var cl = new CommandLineUtilities(args);

            foreach (var option in cl.Options)
            {
                switch (option.Name.ToUpperInvariant())
                {
                case "C":
                case "CONFIG":
                    lightConfig.Config = CommandLineUtilities.ParseStringOption(option);
                    break;

                case "COLOR":
                case "COLOR+":
                case "COLOR-":
                    lightConfig.Color = CommandLineUtilities.ParseBooleanOption(option);
                    break;

                case "DISABLEPATHTRANSLATION":
                    lightConfig.DisablePathTranslation = true;
                    break;

                case "HELP":
                    lightConfig.Help = Args.ParseHelpOption(option);
                    break;

                case "NOLOGO":
                case "NOLOGO+":
                case "NOLOGO-":
                    lightConfig.NoLogo = CommandLineUtilities.ParseBooleanOption(option);
                    break;

                case "FANCYCONSOLE":
                case "FANCYCONSOLE+":
                case "FANCYCONSOLE-":
                case "EXP:FANCYCONSOLE":
                case "EXP:FANCYCONSOLE+":
                case "EXP:FANCYCONSOLE-":
                    lightConfig.FancyConsole = CommandLineUtilities.ParseBooleanOption(option);
                    break;

                case "ENABLEDEDUP":
                case "ENABLEDEDUP+":
                case "ENABLEDEDUP-":
                    lightConfig.EnableDedup = CommandLineUtilities.ParseBooleanOption(option);
                    break;

                case "SERVER":
                    lightConfig.Server = CommandLineUtilities.ParseBoolEnumOption(option, true, ServerMode.Enabled, ServerMode.Disabled);
                    break;

                case "SERVER+":
                    lightConfig.Server = CommandLineUtilities.ParseBoolEnumOption(option, true, ServerMode.Enabled, ServerMode.Disabled);
                    break;

                case "SERVER-":
                    lightConfig.Server = CommandLineUtilities.ParseBoolEnumOption(option, false, ServerMode.Enabled, ServerMode.Disabled);
                    break;

                case "SERVERMAXIDLETIMEINMINUTES":
                    lightConfig.ServerIdleTimeInMinutes = CommandLineUtilities.ParseInt32Option(option, 1, int.MaxValue);
                    break;

                case "SERVERDEPLOYMENTDIR":
                    lightConfig.ServerDeploymentDirectory = CommandLineUtilities.ParseStringOption(option);
                    break;

                case "SUBSTSOURCE":
                    lightConfig.SubstSource = CommandLineUtilities.ParseStringOption(option);
                    break;

                case "SUBSTTARGET":
                    lightConfig.SubstTarget = CommandLineUtilities.ParseStringOption(option);
                    break;
                }
            }

            // This has no attempt at any sort of error handling. Leave that to the real argument parser. Only detect errors
            return(!string.IsNullOrWhiteSpace(lightConfig.Config));
        }
Example #18
0
        static void SafeMain(string[] args)
        {
            int    count = 1;
            string t;
            var    etwProvider = CommandLineUtilities.GetArgument("etw", Guid.Empty);

            Console.WriteLine("TraceSpy Test.");
            Console.WriteLine();
            Console.WriteLine("Press Q, ESC, or CTRL-C to quit");
            Console.WriteLine();
            Console.WriteLine("OutputDebugString");
            Console.WriteLine(" Press O to send an OutputDebugString trace.");
            Console.WriteLine(" Press C to send an OutputDebugString trace every random interval, C again to stop.");

            if (etwProvider != Guid.Empty)
            {
                _etw = new EventProvider(etwProvider);
                Console.WriteLine();
                Console.WriteLine("ETW");
                Console.WriteLine(" Press E to send an ETW trace to provider '" + etwProvider + "'.");
                Console.WriteLine(" Press 1..9 to send 0..9 ETW traces to provider '" + etwProvider + "'.");
                Console.WriteLine("  Combine with Shift to multiply by 10");
                Console.WriteLine("  Combine with Control to multiply by 100");
                Console.WriteLine("  Combine with Alt to multiply by 1000");
            }

            Console.WriteLine();
            do
            {
                var info = Console.ReadKey(true);
                int key  = (int)info.Key;
                int num  = GetFinalNumber(info);
                switch (info.Key)
                {
                case ConsoleKey.Escape:
                    return;

                case ConsoleKey.Q:
                    if (_etw != null)
                    {
                        _etw.Dispose();
                    }
                    return;

                case ConsoleKey.O:
                    t = "ODSTrace #" + count + " from TraceSpyTest. Date:" + DateTime.Now;
                    Console.WriteLine("Sending: '" + t + "'");
                    Trace.WriteLine(t);
                    count++;
                    break;

                case ConsoleKey.C:
                    if (_timer == null)
                    {
                        _timer = new Timer((state) =>
                        {
                            t = "ODS Continuous Trace #" + count + " from TraceSpyTest. Date:" + DateTime.Now + ". " + GetSomeRandomText();
                            Console.WriteLine("Sending: '" + t + "'");
                            Trace.WriteLine(t);
                            count++;
                            _timer.Change(_rnd.Next(100, 2000), 0);
                        });
                        _timer.Change(_rnd.Next(100, 2000), 0);
                    }
                    else
                    {
                        _timer.Dispose();
                        _timer = null;
                    }
                    break;

                case ConsoleKey.E:
                    t = "ETWTrace #" + count + " from TraceSpyTest. Date:" + DateTime.Now;
                    Console.WriteLine("Sending: '" + t + "'");
                    _etw.WriteMessageEvent(t);
                    count++;
                    break;

                default:
                    if (num > 0)
                    {
                        for (int i = 1; i <= num; i++)
                        {
                            t = "Trace #" + count + ", " + i + "/" + num + " from TraceSpyTest. Date:" + DateTime.Now;
                            if (num < 1000 || (i % 1000) == 0)
                            {
                                Console.WriteLine("Sending: '" + t + "'");
                            }
                            _etw.WriteMessageEvent(t);
                            count++;
                        }
                    }
                    break;
                }
            }while (true);
        }
Example #19
0
        /// <inhericdoc />
        public void StartEarlyProcessing(string clientId, IReadOnlyList <string> history)
        {
            // The context only changes when the user executes the corresponding command.
            _azContext?.UpdateContext();

            if (history.Count > 0)
            {
                // We try to find the commands to request predictions for.
                // We should only have "start_of_snippet" when there are no enough Az commands for prediction.
                // We then ignore that when there are new "start_of_snippet".
                // This is the scenario.
                // 1. New-AzResourceGroup -Name ****
                // 2. $resourceName="Test"
                // 3. $resourceLocation="westus2"
                // 4. New-AzVM -Name $resourceName -Location $resourceLocation
                //
                // We'll replace 2 and 3 with "start_of_snippet" but if we request prediction using 2 and 3, that'll reset the
                // workflow. We want to predict only by Az commands. That's to use commands 1 and 4.

                bool isLastTwoCommandsChanged = false;

                if (_lastTwoMaskedCommands.Count == 0)
                {
                    // This is the first time we populate our record. Push the second to last command in history to the
                    // queue. If there is only one command in history, push the command placeholder.

                    if (history.Count() > 1)
                    {
                        string secondToLastLine    = history.TakeLast(AzPredictorConstants.CommandHistoryCountToProcess).First();
                        var    secondToLastCommand = GetAstAndMaskedCommandLine(secondToLastLine);
                        _lastTwoMaskedCommands.Enqueue(secondToLastCommand.IsSupported ? secondToLastCommand.MaskedValue : AzPredictorConstants.CommandPlaceholder);

                        if (secondToLastCommand.IsSupported)
                        {
                            _service.RecordHistory(secondToLastCommand.Ast);
                        }
                    }
                    else
                    {
                        _lastTwoMaskedCommands.Enqueue(AzPredictorConstants.CommandPlaceholder);
                        // We only extract parameter values from the command line in _service.RecordHistory.
                        // So we don't need to do that for a placeholder.
                    }

                    isLastTwoCommandsChanged = true;
                }

                string lastLine               = history.Last();
                var    lastCommand            = GetAstAndMaskedCommandLine(lastLine);
                bool   isLastCommandSupported = lastCommand.IsSupported;

                if (isLastCommandSupported)
                {
                    if (_lastTwoMaskedCommands.Count == 2)
                    {
                        // There are already two commands, dequeue the oldest one.
                        _lastTwoMaskedCommands.Dequeue();
                    }

                    _lastTwoMaskedCommands.Enqueue(lastCommand.Item2);
                    isLastTwoCommandsChanged = true;

                    _service.RecordHistory(lastCommand.Item1);
                }
                else if (_lastTwoMaskedCommands.Count == 1)
                {
                    isLastTwoCommandsChanged = true;
                    var existingInQueue = _lastTwoMaskedCommands.Dequeue();
                    _lastTwoMaskedCommands.Enqueue(AzPredictorConstants.CommandPlaceholder);
                    _lastTwoMaskedCommands.Enqueue(existingInQueue);
                }

                _telemetryClient.OnHistory(new HistoryTelemetryData(clientId, lastCommand.MaskedValue ?? AzPredictorConstants.CommandPlaceholder));

                if (isLastTwoCommandsChanged)
                {
                    // When it's called multiple times, we only need to keep the one for the latest command.

                    _predictionRequestCancellationSource?.Cancel();
                    _predictionRequestCancellationSource = new CancellationTokenSource();
                    // Need to create a new object to hold the string. They're used in a seperate thread the the contents in
                    // _lastTwoMaskedCommands may change when the method is called again.
                    var       lastTwoMaskedCommands = new List <string>(_lastTwoMaskedCommands);
                    Exception exception             = null;
                    var       hasSentHttpRequest    = false;

                    // We don't need to block on the task. It sends the HTTP request and update prediction list. That can run at the background.
                    Task.Run(async() =>
                    {
                        try
                        {
                            await _service.RequestPredictionsAsync(lastTwoMaskedCommands, _predictionRequestCancellationSource.Token);
                        }
                        catch (ServiceRequestException e)
                        {
                            hasSentHttpRequest = e.IsRequestSent;
                            exception          = e.InnerException;
                        }
                        catch (Exception e)
                        {
                            exception = e;
                        }
                        finally
                        {
                            _telemetryClient.OnRequestPrediction(new RequestPredictionTelemetryData(clientId, lastTwoMaskedCommands,
                                                                                                    hasSentHttpRequest,
                                                                                                    (exception is OperationCanceledException ? null : exception)));
                        }
                    }, _predictionRequestCancellationSource.Token);
                }
            }

            (CommandAst Ast, string MaskedValue, bool IsSupported) GetAstAndMaskedCommandLine(string commandLine)
            {
                var asts          = Parser.ParseInput(commandLine, out _, out _);
                var allNestedAsts = asts?.FindAll((ast) => ast is CommandAst, true);
                var commandAst    = allNestedAsts?.LastOrDefault() as CommandAst;

                var    commandName       = commandAst?.CommandElements?.FirstOrDefault().ToString();
                bool   isSupported       = _service.IsSupportedCommand(commandName);
                string maskedCommandLine = CommandLineUtilities.MaskCommandLine(commandAst);

                return(commandAst, maskedCommandLine, isSupported);
            }
        }
Example #20
0
    static int Main()
    {
#if USE_EVENTSOURCE_REFLECTION
        // If this app does not take a dependency on a specific EventSource implementation we'll need to use the EventSource
        // type that represents the base type of the custom event source that needs to be registered. To accomplish this we
        // need to set up a separate domain that has the app base set to the location of the assembly to be registered, and
        // the config file set to the config file that might be associated with this assebmly, in the case the assembly is
        // an EXE. Having the worker domain set up in this way allows for the regular assembly lookup rules to kick in and
        // perform the expected lookup the the EventSource-base assembly based on the passed in assembly.
        // In the worker domain we load in the "reflection-only" context the assembly passed in as an argument and allow its
        // dependency to be loaded as well. Once the base assembly is loaded in the reflection-only context we retrieve its
        // location and call LoadFrom() on the assembly in order to get access to the EventSource static methods we need to
        // call.
        var workerDomainFriendlyName = "eventRegister_workerDomain";
        if (AppDomain.CurrentDomain.FriendlyName != workerDomainFriendlyName)
        {
            // See code:#CommandLineDefinitions for Command line defintions
            CommandLine commandLine = new CommandLine();
            var         ads         = new AppDomainSetup();
            // ads.PrivateBinPath = Path.GetDirectoryName(Path.GetFullPath(commandLine.DllPath));
            ads.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory;
            // ads.ApplicationBase = Path.GetDirectoryName(Path.GetFullPath(commandLine.DllPath));
            // var configName = Path.GetFullPath(commandLine.DllPath) + ".config";
            // if (Path.GetExtension(commandLine.DllPath) == ".exe" && File.Exists(configName))
            //     ads.ConfigurationFile = configName;
            var workerDom = AppDomain.CreateDomain(workerDomainFriendlyName, null, ads, new System.Security.PermissionSet(System.Security.Permissions.PermissionState.Unrestricted));
            // make sure the worker domain is aware of the additional paths to probe when resolving the EventSource base type
            if (commandLine.ReferencePath != null)
            {
                workerDom.SetData("ReferencePath", Environment.ExpandEnvironmentVariables(commandLine.ReferencePath));
            }
            return(workerDom.ExecuteAssembly(typeof(Program).Assembly.Location));
        }
        else
#endif
        return(CommandLineUtilities.RunConsoleMainWithExceptionProcessing(delegate
        {
            // See code:#CommandLineDefinitions for Command line defintions
            CommandLine commandLine = new CommandLine();
            List <Tuple <string, string> > regDlls;
            EventSourceReflectionProxy.ManifestGenerator = commandLine.ManifestGenerator;
            switch (commandLine.Command)
            {
            // Create the XML description in the data directory "will be called
            case CommandLine.CommandType.DumpManifest:
                var manifests = CreateManifestsFromManagedDll(commandLine.DllPath, commandLine.ManifestPrefix);
                if (manifests.Count == 0)
                {
                    Console.WriteLine("Info: No event source classes " + (commandLine.ForceAll ? "" : "needing registration ") + "found in " + commandLine.DllPath);
                }
                break;

            case CommandLine.CommandType.CompileManifest:
                CompileManifest(commandLine.ManPath, System.IO.Path.ChangeExtension(commandLine.ManPath, ".dll"));
                break;

            case CommandLine.CommandType.DumpRegDlls:
                regDlls = CreateRegDllsFromManagedDll(commandLine.DllPath, commandLine.ForceAll, commandLine.ManifestPrefix);
                if (regDlls.Count == 0)
                {
                    Console.WriteLine("Info: No event source classes " + (commandLine.ForceAll ? "" : "needing registration ") + "found in " + commandLine.DllPath);
                }
                break;

            case CommandLine.CommandType.Install:
                regDlls = RegisterManagedDll(commandLine.DllPath, false, commandLine.ManifestPrefix);
                if (regDlls.Count == 0)
                {
                    Console.WriteLine("Info: No event source classes " + (commandLine.ForceAll ? "" : "needing registration ") + "found in " + commandLine.DllPath);
                }
                break;

            case CommandLine.CommandType.Uninstall:
                regDlls = RegisterManagedDll(commandLine.DllPath, true, commandLine.ManifestPrefix);
                if (regDlls.Count == 0)
                {
                    Console.WriteLine("Info: No event source classes " + (commandLine.ForceAll ? "" : "needing registration ") + "found in " + commandLine.DllPath);
                }
                break;
            }
            return 0;
        }));
    }
Example #21
0
        /// <summary>
        /// Attempts to parse the configuration. This is a subset of what's parsed in Args
        /// </summary>
        /// <remarks>
        /// Keep the subset of parsing here limited to whatever's needed to run the client process
        /// </remarks>
        public static bool TryParse(string[] args, out LightConfig lightConfig)
        {
            lightConfig = new LightConfig();

            var cl = new CommandLineUtilities(args);

            foreach (var option in cl.Options)
            {
                switch (option.Name.ToUpperInvariant())
                {
                case "C":
                case "CONFIG":
                    lightConfig.Config = CommandLineUtilities.ParseStringOption(option);
                    break;

                case "COLOR":
                case "COLOR+":
                case "COLOR-":
                    lightConfig.Color = CommandLineUtilities.ParseBooleanOption(option);
                    break;

                case "DISABLEPATHTRANSLATION":
                    lightConfig.DisablePathTranslation = true;
                    break;

                case "HELP":
                    lightConfig.Help = Args.ParseHelpOption(option);
                    break;

                case "NOLOGO":
                case "NOLOGO+":
                case "NOLOGO-":
                    lightConfig.NoLogo = CommandLineUtilities.ParseBooleanOption(option);
                    break;

                case "FANCYCONSOLE":
                case "FANCYCONSOLE+":
                case "FANCYCONSOLE-":
                case "EXP:FANCYCONSOLE":
                case "EXP:FANCYCONSOLE+":
                case "EXP:FANCYCONSOLE-":
                    lightConfig.FancyConsole = CommandLineUtilities.ParseBooleanOption(option);
                    break;

                case "ENABLEDEDUP":
                case "ENABLEDEDUP+":
                case "ENABLEDEDUP-":
                    lightConfig.EnableDedup = CommandLineUtilities.ParseBooleanOption(option);
                    break;

                case "HASHTYPE":
                    lightConfig.HashType = CommandLineUtilities.ParseStringOption(option);
                    break;

                case "SERVER":
                    lightConfig.Server = CommandLineUtilities.ParseBoolEnumOption(option, true, ServerMode.Enabled, ServerMode.Disabled);
                    break;

                case "SERVER+":
                    lightConfig.Server = CommandLineUtilities.ParseBoolEnumOption(option, true, ServerMode.Enabled, ServerMode.Disabled);
                    break;

                case "SERVER-":
                    lightConfig.Server = CommandLineUtilities.ParseBoolEnumOption(option, false, ServerMode.Enabled, ServerMode.Disabled);
                    break;

                case "SERVERMAXIDLETIMEINMINUTES":
                    lightConfig.ServerIdleTimeInMinutes = CommandLineUtilities.ParseInt32Option(option, 1, int.MaxValue);
                    break;

                case "SERVERDEPLOYMENTDIR":
                    lightConfig.ServerDeploymentDirectory = CommandLineUtilities.ParseStringOption(option);
                    break;

                case "SUBSTSOURCE":
                    lightConfig.SubstSource = CommandLineUtilities.ParseStringOption(option);
                    break;

                case "SUBSTTARGET":
                    lightConfig.SubstTarget = CommandLineUtilities.ParseStringOption(option);
                    break;

                case "RUNINSUBST":
                case "RUNINSUBST+":
                    lightConfig.RunInSubst = true;
                    break;

                case "RUNINSUBST-":
                    lightConfig.RunInSubst = false;
                    break;
                }
            }

            // This has no attempt at any sort of error handling. Leave that to the real argument parser. Only detect errors
            // If RunInSubst is specified without an explicit subst source, we fail if the config file does not exist since we need to compute the parent directory of the main config during light config interpretation
            return(!string.IsNullOrWhiteSpace(lightConfig.Config) && (!lightConfig.RunInSubst || !string.IsNullOrEmpty(lightConfig.SubstSource) || File.Exists(lightConfig.Config)));
        }
Example #22
0
        public ParameterSet(CommandAst commandAst, IAzContext azContext = null)
        {
            Validation.CheckArgument(commandAst, $"{nameof(commandAst)} cannot be null.");

            _commandAst = commandAst;
            _azContext  = azContext;

            var parameters            = new List <Parameter>();
            CommandParameterAst param = null;
            Ast arg = null;

            // positional parameters must be before named parameters.
            // This loop will convert them to named parameters.
            // Loop through all the parameters. The first element of CommandElements is the command name, so skip it.
            bool hasSeenNamedParameter      = false;
            bool hasSeenIncompleteParameter = false;

            for (var i = 1; i < commandAst.CommandElements.Count(); ++i)
            {
                var elem = commandAst.CommandElements[i];

                if (elem is CommandParameterAst p)
                {
                    if (hasSeenIncompleteParameter)
                    {
                        throw new CommandLineException("'-' is in the middle of the parameter list.");
                    }

                    hasSeenNamedParameter = true;
                    AddNamedParameter(param, arg);
                    // In case there is a switch parameter, we store the parameter name/value and add them when we see the next pair.
                    param = p;
                    arg   = null;
                }
                else if (AzPredictorConstants.ParameterIndicator == elem?.ToString().Trim().FirstOrDefault())
                {
                    // We have an incomplete command line such as
                    // `New-AzResourceGroup -Name ResourceGroup01 -Location WestUS -`
                    // We'll ignore the incomplete parameter.
                    AddNamedParameter(param, arg);
                    param = null;
                    arg   = null;
                    hasSeenIncompleteParameter = true;
                    parameters.Add(new Parameter(AzPredictorConstants.DashParameterName, null, false));
                }
                else
                {
                    if (hasSeenIncompleteParameter || (hasSeenNamedParameter && param == null))
                    {
                        throw new CommandLineException("Positional parameters must be before named parameters.");
                    }

                    if (param == null)
                    {
                        // This is a positional parameter.
                        var pair = BoundParameters.First((pair) => pair.Value.Value == elem);

                        var parameterName  = pair.Key;
                        var parameterValue = CommandLineUtilities.EscapePredictionText(pair.Value.Value.ToString());
                        parameters.Add(new Parameter(parameterName, parameterValue, true));
                        BoundParameters.Remove(pair); // Remove it so that we can match another parameter with the same value.
                    }
                    else
                    {
                        arg = elem;
                        AddNamedParameter(param, arg);
                        param = null;
                        arg   = null;
                    }
                }
            }

            Validation.CheckInvariant <CommandLineException>((param != null) || (arg == null));
            AddNamedParameter(param, arg);

            Parameters = parameters;

            void AddNamedParameter(CommandParameterAst parameter, Ast parameterValue)
            {
                if (parameter != null)
                {
                    var value = parameterValue?.ToString();
                    if (value == null)
                    {
                        value = parameter.Argument?.ToString();
                    }

                    if (value != null)
                    {
                        value = CommandLineUtilities.UnescapePredictionText(value);
                    }

                    parameters.Add(new Parameter(parameter.ParameterName, value, false));
                }
            }
        }
Example #23
0
        private static Options ParseOptions(string[] toolArgs)
        {
            var opts = new OptionsBuilder(Options.Defaults);

            var cli = new CommandLineUtilities(toolArgs);

            foreach (var opt in cli.Options)
            {
                switch (opt.Name.TrimEnd('-', '+'))
                {
                case ArgVerbose:
                case "v":
                    opts.Verbose = CommandLineUtilities.ParseBooleanOption(opt);
                    break;

                case ArgLogToStdOut:
                case "o":
                    opts.LogToStdOut = CommandLineUtilities.ParseBooleanOption(opt);
                    break;

                case "numKextConnections":
                case "c":
                    Console.WriteLine($"*** WARNING *** option /{opt.Name} has no effect any longer");
                    break;

                case ArgReportQueueSizeMB:
                case "r":
                    opts.ReportQueueSizeMB = CommandLineUtilities.ParseUInt32Option(opt, 1, 1024);
                    break;

                case ArgEnableReportBatching:
                case "b":
                    opts.EnableReportBatching = CommandLineUtilities.ParseBooleanOption(opt);
                    break;

                case ArgEnableStatistics:
                case "s":
                    opts.EnableTelemetry = CommandLineUtilities.ParseBooleanOption(opt);
                    break;

                case ArgProcessTimeout:
                case "t":
                    // Max is currently set to 4 hours and should suffice
                    opts.ProcessTimeout = CommandLineUtilities.ParseInt32Option(opt, (int)s_defaultProcessTimeOut, (int)s_defaultProcessTimeOutMax);
                    break;

                case ArgTrackDirectoryCreation:
                case "d":
                    opts.TrackDirectoryCreation = CommandLineUtilities.ParseBooleanOption(opt);
                    break;

                case ArgUseEndpointSecuritySandbox:
                case "e":
                    opts.UseEndpointSecuritySandbox = CommandLineUtilities.ParseBooleanOption(opt);
                    break;

                default:
                    throw new InvalidArgumentException($"Unrecognized option {opt.Name}");
                }
            }

            return(opts.Finish());
        }
        /// <inhericdoc />
        public void StartEarlyProcessing(IReadOnlyList <string> history)
        {
            // The context only changes when the user executes the corresponding command.
            _azContext?.UpdateContext();

            if (history.Count > 0)
            {
                if (_lastTwoMaskedCommands.Any())
                {
                    _lastTwoMaskedCommands.Dequeue();
                }
                else
                {
                    // This is the first time we populate our record. Push the second to last command in history to the
                    // queue. If there is only one command in history, push the command placeholder.

                    if (history.Count() > 1)
                    {
                        string secondToLastLine    = history.TakeLast(AzPredictorConstants.CommandHistoryCountToProcess).First();
                        var    secondToLastCommand = GetAstAndMaskedCommandLine(secondToLastLine);
                        _lastTwoMaskedCommands.Enqueue(secondToLastCommand.Item2);
                        _service.RecordHistory(secondToLastCommand.Item1);
                    }
                    else
                    {
                        _lastTwoMaskedCommands.Enqueue(AzPredictorConstants.CommandPlaceholder);
                        // We only extract parameter values from the command line in _service.RecordHistory.
                        // So we don't need to do that for a placeholder.
                    }
                }

                string lastLine    = history.Last();
                var    lastCommand = GetAstAndMaskedCommandLine(lastLine);

                _lastTwoMaskedCommands.Enqueue(lastCommand.Item2);

                if ((lastCommand.Item2 != null) && !string.Equals(AzPredictorConstants.CommandPlaceholder, lastCommand.Item2, StringComparison.Ordinal))
                {
                    _service.RecordHistory(lastCommand.Item1);
                }

                _telemetryClient.OnHistory(new HistoryTelemetryData(lastCommand.Item2));
                _service.RequestPredictions(_lastTwoMaskedCommands);
            }

            ValueTuple <CommandAst, string> GetAstAndMaskedCommandLine(string commandLine)
            {
                var    asts              = Parser.ParseInput(commandLine, out _, out _);
                var    allNestedAsts     = asts?.FindAll((ast) => ast is CommandAst, true);
                var    commandAst        = allNestedAsts?.LastOrDefault() as CommandAst;
                string maskedCommandLine = null;

                var commandName = commandAst?.CommandElements?.FirstOrDefault().ToString();

                if (_service.IsSupportedCommand(commandName))
                {
                    maskedCommandLine = CommandLineUtilities.MaskCommandLine(commandAst);
                }
                else
                {
                    maskedCommandLine = AzPredictorConstants.CommandPlaceholder;
                }

                return(ValueTuple.Create(commandAst, maskedCommandLine));
            }
        }