Upgrade to latest System.CommandLine version (#668)
authorMike McLaughlin <mikem@microsoft.com>
Fri, 6 Dec 2019 23:13:16 +0000 (15:13 -0800)
committerGitHub <noreply@github.com>
Fri, 6 Dec 2019 23:13:16 +0000 (15:13 -0800)
Upgrade to latest System.CommandLine version

Use collection initializers

27 files changed:
diagnostics.sln
eng/Versions.props
src/Microsoft.Diagnostics.Repl/Command/CommandProcessor.cs
src/Tools/Common/CommandExtensions.cs [new file with mode: 0644]
src/Tools/Common/CommandLineException.cs [deleted file]
src/Tools/Common/Commands/ProcessStatus.cs
src/Tools/Common/ConsoleCancellation.cs [deleted file]
src/Tools/Common/DebugUtil.cs [deleted file]
src/Tools/dotnet-counters/Program.cs
src/Tools/dotnet-counters/dotnet-counters.csproj
src/Tools/dotnet-dump/Analyzer.cs
src/Tools/dotnet-dump/Commands/SOSCommand.cs
src/Tools/dotnet-dump/Program.cs
src/Tools/dotnet-dump/dotnet-dump.csproj
src/Tools/dotnet-gcdump/CommandLine/CollectCommandHandler.cs
src/Tools/dotnet-gcdump/CommandLine/ProcessStatusCommandHandler.cs [deleted file]
src/Tools/dotnet-gcdump/Program.cs
src/Tools/dotnet-gcdump/dotnet-gcdump.csproj
src/Tools/dotnet-sos/Program.cs
src/Tools/dotnet-sos/dotnet-sos.csproj
src/Tools/dotnet-trace/CommandLine/Commands/CollectCommand.cs
src/Tools/dotnet-trace/CommandLine/Commands/ConvertCommand.cs
src/Tools/dotnet-trace/CommandLine/Commands/ListProcessesCommandHandler.cs [deleted file]
src/Tools/dotnet-trace/CommandLine/Commands/ListProfilesCommandHandler.cs
src/Tools/dotnet-trace/CommandLine/Options/CommonOptions.cs
src/Tools/dotnet-trace/Program.cs
src/Tools/dotnet-trace/dotnet-trace.csproj

index 45df2c9e38a392506ff2b41e7b2fabb33f2504de..1ba3fc9c4d127f577c72efecba0aa56e67c80c70 100644 (file)
@@ -63,6 +63,16 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tracee", "src\tests\Tracee\
 EndProject
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EventPipe.UnitTests", "src\tests\eventpipe\EventPipe.UnitTests.csproj", "{CED9ABBA-861E-4C0A-9359-22351208EF27}"
 EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Common", "Common", "{298AE119-6625-4604-BDE5-0765DC34C856}"
+       ProjectSection(SolutionItems) = preProject
+               src\Tools\Common\CommandExtensions.cs = src\Tools\Common\CommandExtensions.cs
+       EndProjectSection
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Commands", "Commands", "{C457CBCD-3A8D-4402-9A2B-693A0390D3F9}"
+       ProjectSection(SolutionItems) = preProject
+               src\Tools\Common\Commands\ProcessStatus.cs = src\Tools\Common\Commands\ProcessStatus.cs
+       EndProjectSection
+EndProject
 Global
        GlobalSection(SolutionConfigurationPlatforms) = preSolution
                Checked|Any CPU = Checked|Any CPU
@@ -1090,6 +1100,8 @@ Global
                {6F4DD2F8-1C7B-4A87-B7E5-1BEE9F5AC128} = {03479E19-3F18-49A6-910A-F5041E27E7C0}
                {C79D6069-2C18-48CB-846E-71F7168C2F7D} = {03479E19-3F18-49A6-910A-F5041E27E7C0}
                {CED9ABBA-861E-4C0A-9359-22351208EF27} = {03479E19-3F18-49A6-910A-F5041E27E7C0}
+               {298AE119-6625-4604-BDE5-0765DC34C856} = {B62728C8-1267-4043-B46F-5537BBAEC692}
+               {C457CBCD-3A8D-4402-9A2B-693A0390D3F9} = {298AE119-6625-4604-BDE5-0765DC34C856}
        EndGlobalSection
        GlobalSection(ExtensibilityGlobals) = postSolution
                SolutionGuid = {46465737-C938-44FC-BE1A-4CE139EBB5E0}
index 186c6fa88ff2b771d2462d9c77b58bfad12392f6..886f4afbc812192f84f2944d3d3aea5c9bab168d 100644 (file)
@@ -25,8 +25,8 @@
     <MicrosoftDiagnosticsRuntimeVersion>1.1.46104</MicrosoftDiagnosticsRuntimeVersion>
     <MicrosoftDiaSymReaderNativePackageVersion>1.7.0</MicrosoftDiaSymReaderNativePackageVersion>
     <MicrosoftDiagnosticsTracingTraceEventVersion>2.0.44</MicrosoftDiagnosticsTracingTraceEventVersion>
-    <SystemCommandLineExperimentalVersion>0.2.0-alpha.19254.1</SystemCommandLineExperimentalVersion>
-    <SystemCommandLineRenderingVersion>0.2.0-alpha.19254.1</SystemCommandLineRenderingVersion>
+    <SystemCommandLineExperimentalVersion>0.3.0-alpha.19602.1</SystemCommandLineExperimentalVersion>
+    <SystemCommandLineRenderingVersion>0.3.0-alpha.19602.1</SystemCommandLineRenderingVersion>
     <SystemMemoryVersion>4.5.3</SystemMemoryVersion>
     <XUnitVersion>2.4.1</XUnitVersion>
     <XUnitAbstractionsVersion>2.0.3</XUnitAbstractionsVersion>
index 745bca2a5472177bbb683a057e6cf2fe2cb9f28b..4a2791e17dade47892412b85cebcfed34c726942 100644 (file)
@@ -118,32 +118,32 @@ namespace Microsoft.Diagnostics.Repl
                 {
                     command = new Command(commandAttribute.Name, commandAttribute.Help);
                     var properties = new List<(PropertyInfo, Option)>();
-                    PropertyInfo argument = null;
+                    var arguments = new List<(PropertyInfo, Argument)>();
 
                     foreach (PropertyInfo property in type.GetProperties().Where(p => p.CanWrite))
                     {
                         var argumentAttribute = (ArgumentAttribute)property.GetCustomAttributes(typeof(ArgumentAttribute), inherit: false).SingleOrDefault();
                         if (argumentAttribute != null)
                         {
-                            if (argument != null) {
-                                throw new ArgumentException($"More than one ArgumentAttribute in command class: {type.Name}");
-                            }
                             IArgumentArity arity = property.PropertyType.IsArray ? ArgumentArity.ZeroOrMore : ArgumentArity.ZeroOrOne;
 
-                            command.Argument = new Argument {
+                            var argument = new Argument {
                                 Name = argumentAttribute.Name ?? property.Name.ToLowerInvariant(),
                                 Description = argumentAttribute.Help,
                                 ArgumentType = property.PropertyType,
                                 Arity = arity
                             };
-                            argument = property;
+                            command.AddArgument(argument);
+                            arguments.Add((property, argument));
                         }
                         else
                         {
                             var optionAttribute = (OptionAttribute)property.GetCustomAttributes(typeof(OptionAttribute), inherit: false).SingleOrDefault();
                             if (optionAttribute != null)
                             {
-                                var option = new Option(optionAttribute.Name ?? BuildAlias(property.Name), optionAttribute.Help, new Argument { ArgumentType = property.PropertyType });
+                                var option = new Option(optionAttribute.Name ?? BuildAlias(property.Name), optionAttribute.Help) {
+                                    Argument = new Argument { ArgumentType = property.PropertyType }
+                                };
                                 command.AddOption(option);
                                 properties.Add((property, option));
 
@@ -160,7 +160,7 @@ namespace Microsoft.Diagnostics.Repl
                         }
                     }
 
-                    var handler = new Handler(this, commandAttribute.AliasExpansion, argument, properties, type);
+                    var handler = new Handler(this, commandAttribute.AliasExpansion, arguments, properties, type);
                     _commandHandlers.Add(command.Name, handler);
                     command.Handler = handler;
 
@@ -201,18 +201,18 @@ namespace Microsoft.Diagnostics.Repl
         {
             private readonly CommandProcessor _commandProcessor;
             private readonly string _aliasExpansion;
-            private readonly PropertyInfo _argument;
+            private readonly IEnumerable<(PropertyInfo Property, Argument Argument)> _arguments;
             private readonly IEnumerable<(PropertyInfo Property, Option Option)> _properties;
 
             private readonly ConstructorInfo _constructor;
             private readonly MethodInfo _methodInfo;
             private readonly MethodInfo _methodInfoHelp;
 
-            public Handler(CommandProcessor commandProcessor, string aliasExpansion, PropertyInfo argument, IEnumerable<(PropertyInfo, Option)> properties, Type type)
+            public Handler(CommandProcessor commandProcessor, string aliasExpansion, IEnumerable<(PropertyInfo, Argument)> arguments, IEnumerable<(PropertyInfo, Option)> properties, Type type)
             {
                 _commandProcessor = commandProcessor;
                 _aliasExpansion = aliasExpansion;
-                _argument = argument;
+                _arguments = arguments;
                 _properties = properties;
 
                 _constructor = type.GetConstructors().SingleOrDefault((info) => info.GetParameters().Length == 0) ?? 
@@ -303,19 +303,19 @@ namespace Microsoft.Diagnostics.Repl
                     property.Property.SetValue(instance, value);
                 }
 
-                if (context != null && _argument != null)
+                if (context != null)
                 {
-                    object value = null;
-                    ArgumentResult result = context.ParseResult.CommandResult.ArgumentResult;
-                    switch (result)
+                    IEnumerable<ArgumentResult> argumentResults = context.ParseResult.CommandResult.Children.OfType<ArgumentResult>();
+
+                    foreach ((PropertyInfo Property, Argument Argument) argument in _arguments)
                     {
-                        case SuccessfulArgumentResult successful:
-                            value = successful.Value;
-                            break;
-                        case FailedArgumentResult failed:
-                            throw new InvalidOperationException(failed.ErrorMessage);
+                        ArgumentResult argumentResult = argumentResults.Where((result) => result.Argument == argument.Argument).SingleOrDefault();
+                        if (argumentResult != null)
+                        {
+                            object value = argumentResult.GetValueOrDefault();
+                            argument.Property.SetValue(instance, value);
+                        }
                     }
-                    _argument.SetValue(instance, value);
                 }
             }
 
diff --git a/src/Tools/Common/CommandExtensions.cs b/src/Tools/Common/CommandExtensions.cs
new file mode 100644 (file)
index 0000000..cde9a19
--- /dev/null
@@ -0,0 +1,20 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.CommandLine;
+using System.CommandLine.Invocation;
+
+namespace Microsoft.Tools.Common
+{
+    public static class CommandExtenions
+    {
+        /// <summary>
+        /// Allows the command handler to be included in the collection initializer.
+        /// </summary>
+        public static void Add(this Command command, ICommandHandler handler)
+        {
+            command.Handler = handler;
+        }
+    }
+}
diff --git a/src/Tools/Common/CommandLineException.cs b/src/Tools/Common/CommandLineException.cs
deleted file mode 100644 (file)
index 03b0776..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System;
-using System.Runtime.Serialization;
-
-namespace Microsoft.Internal.Utilities
-{
-    public class CommandLineException : Exception
-    {
-        public CommandLineException()
-        {
-        }
-
-        public CommandLineException(string message) : base(message)
-        {
-        }
-
-        public CommandLineException(string message, Exception innerException) : base(message, innerException)
-        {
-        }
-
-        protected CommandLineException(SerializationInfo info, StreamingContext context) : base(info, context)
-        {
-        }
-    }
-}
index 8fc3ce68a80321eaafd291f37346ebe46296cfef..34c3227b0285576b47818ad2a50947f2cd54be20 100644 (file)
@@ -2,18 +2,24 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
+using Microsoft.Diagnostics.NETCore.Client;
 using System;
 using System.CommandLine;
-using System.Diagnostics;
+using System.CommandLine.Invocation;
 using System.Linq;
 using System.Text;
-
-using Microsoft.Diagnostics.NETCore.Client;
+using Process = System.Diagnostics.Process;
 
 namespace Microsoft.Internal.Common.Commands
 {
     public class ProcessStatusCommandHandler
     {
+        public static Command ProcessStatusCommand(string description) =>
+            new Command(name: "ps", description)
+            {
+                Handler = CommandHandler.Create<IConsole>(PrintProcessStatus)
+            };
+
         /// <summary>
         /// Print the current list of available .NET core processes for diagnosis and their statuses
         /// </summary>
diff --git a/src/Tools/Common/ConsoleCancellation.cs b/src/Tools/Common/ConsoleCancellation.cs
deleted file mode 100644 (file)
index 28fecac..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Threading;
-using System.Threading.Tasks;
-using McMaster.Extensions.CommandLineUtils;
-
-namespace Microsoft.Internal.Utilities
-{
-    public static class ConsoleCancellationExtensions
-    {
-        public static CancellationToken GetCtrlCToken(this IConsole console)
-        {
-            var cts = new CancellationTokenSource();
-            console.CancelKeyPress += (sender, args) =>
-            {
-                if (cts.IsCancellationRequested)
-                {
-                    // Terminate forcibly, the user pressed Ctrl-C a second time
-                    args.Cancel = false;
-                }
-                else
-                {
-                    // Don't terminate, just trip the token
-                    args.Cancel = true;
-                    cts.Cancel();
-                }
-            };
-            return cts.Token;
-        }
-
-        public static Task WaitForCtrlCAsync(this IConsole console)
-        {
-            var tcs = new TaskCompletionSource<object>();
-            console.CancelKeyPress += (sender, args) =>
-            {
-                // Don't terminate, just trip the task
-                args.Cancel = true;
-                tcs.TrySetResult(null);
-            };
-            return tcs.Task;
-        }
-    }
-}
diff --git a/src/Tools/Common/DebugUtil.cs b/src/Tools/Common/DebugUtil.cs
deleted file mode 100644 (file)
index d3dcc6d..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System;
-using System.Diagnostics;
-using System.Linq;
-
-namespace Microsoft.Internal.Utilities
-{
-    internal static class DebugUtil
-    {
-        [Conditional("DEBUG")]
-        public static void WaitForDebuggerIfRequested(ref string[] args)
-        {
-            if (args.Any(a => a == "--debug"))
-            {
-                args = args.Where(a => a != "--debug").ToArray();
-                Console.WriteLine($"Ready for debugger to attach. Process ID: {Process.GetCurrentProcess().Id}.");
-                Console.WriteLine("Press ENTER to continue.");
-                Console.ReadLine();
-            }
-        }
-    }
-}
index ca6d20b9f9deef7fab0c2d5d2f226cf780d35c24..6fc086d2152f3ff45c608f1d04737297dfaba6e1 100644 (file)
@@ -2,7 +2,11 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
+using Microsoft.Diagnostics.NETCore.Client;
+using Microsoft.Internal.Common.Commands;
+using Microsoft.Tools.Common;
 using System;
+using System.Collections.Generic;
 using System.CommandLine;
 using System.CommandLine.Binding;
 using System.CommandLine.Builder;
@@ -10,9 +14,6 @@ using System.CommandLine.Invocation;
 using System.Linq;
 using System.Threading;
 using System.Threading.Tasks;
-using System.Collections.Generic;
-using Microsoft.Diagnostics.NETCore.Client;
-using Microsoft.Internal.Common.Commands;
 
 namespace Microsoft.Diagnostics.Tools.Counters
 {
@@ -24,67 +25,72 @@ namespace Microsoft.Diagnostics.Tools.Counters
 
         private static Command MonitorCommand() =>
             new Command(
-                "monitor", 
-                "Start monitoring a .NET application", 
-                new Option[] { ProcessIdOption(), RefreshIntervalOption() },
-                argument: CounterList(),
-                handler: CommandHandler.Create<CancellationToken, List<string>, IConsole, int, int>(new CounterMonitor().Monitor));
+                name: "monitor",
+                description: "Start monitoring a .NET application")
+            {
+                // Handler
+                CommandHandler.Create<CancellationToken, List<string>, IConsole, int, int>(new CounterMonitor().Monitor),
+                // Arguments and Options
+                CounterList(), ProcessIdOption(), RefreshIntervalOption()
+            };
 
         private static Command CollectCommand() =>
             new Command(
-                "collect",
-                "Monitor counters in a .NET application and export the result into a file",
-                new Option[] { ProcessIdOption(), RefreshIntervalOption(), ExportFormatOption(), ExportFileNameOption() },
-                argument: CounterList(),
-                handler: HandlerDescriptor.FromDelegate((ExportDelegate)new CounterMonitor().Collect).GetCommandHandler());
+                name: "collect",
+                description: "Monitor counters in a .NET application and export the result into a file")
+            {
+                // Handler
+                HandlerDescriptor.FromDelegate((ExportDelegate)new CounterMonitor().Collect).GetCommandHandler(),
+                // Arguments and Options
+                CounterList(), ProcessIdOption(), RefreshIntervalOption(), ExportFormatOption(), ExportFileNameOption()
+            };
 
         private static Option ProcessIdOption() =>
             new Option(
-                new[] { "-p", "--process-id" }, 
-                "The ID of the process that will be monitored.",
-                new Argument<int> { Name = "pid" });
+                aliases: new[] { "-p", "--process-id" },
+                description: "The process id that will be monitored.")
+            {
+                Argument = new Argument<int>(name: "pid")
+            };
 
         private static Option RefreshIntervalOption() =>
             new Option(
-                new[] { "--refresh-interval" }, 
-                "The number of seconds to delay between updating the displayed counters.",
-                new Argument<int>(defaultValue: 1) { Name = "refresh-interval" });
+                alias: "--refresh-interval",
+                description: "The number of seconds to delay between updating the displayed counters.")
+            {
+                Argument = new Argument<int>(name: "refresh-interval", defaultValue: 1)
+            };
 
-        private static Option ExportFormatOption() => 
+        private static Option ExportFormatOption() =>
             new Option(
-                new[] { "--format" },
-                "The format of exported counter data.",
-                new Argument<CountersExportFormat>(defaultValue: CountersExportFormat.csv) { Name = "format" });
+                alias: "--format",
+                description: "The format of exported counter data.")
+            {
+                Argument = new Argument<CountersExportFormat>(name: "format", defaultValue: CountersExportFormat.csv)
+            };
 
-        private static Option ExportFileNameOption() => 
+        private static Option ExportFileNameOption() =>
             new Option(
-                new[] { "-o", "--output" },
-                "The output file name.",
-                new Argument<string>(defaultValue: "counter") { Name = "output" });
+                aliases: new[] { "-o", "--output" },
+                description: "The output file name.") 
+            {
+                Argument = new Argument<string>(name: "output", defaultValue: "counter")
+            };
 
         private static Argument CounterList() =>
-            new Argument<List<string>> {
-                Name = "counter_list",
-                Description = @"A space separated list of counters. Counters can be specified provider_name[:counter_name].
-                If the provider_name is used without a qualifying counter_name then all counters will be shown. To discover 
-                provider and counter names, use the list command.
-                .",
+            new Argument<List<string>>(name: "counter_list", defaultValue: new List<string>()) 
+            {
+                Description = @"A space separated list of counters. Counters can be specified provider_name[:counter_name]. If the provider_name is used without a qualifying counter_name then all counters will be shown. To discover provider and counter names, use the list command.",
                 Arity = ArgumentArity.ZeroOrMore
             };
 
         private static Command ListCommand() =>
             new Command(
-                "list", 
-                "Display a list of counter names and descriptions, grouped by provider.", 
-                new Option[] { },
-                handler: CommandHandler.Create<IConsole>(List));
-
-        private static Command ProcessStatusCommand() =>
-            new Command(
-                "ps",
-                "Display a list of dotnet processes that can be monitored.",
-                new Option[] { },
-                handler: CommandHandler.Create<IConsole>(ProcessStatusCommandHandler.PrintProcessStatus));
+                name: "list",
+                description: "Display a list of counter names and descriptions, grouped by provider.")
+            {
+                Handler = CommandHandler.Create<IConsole>(List)
+            };
 
         public static int List(IConsole console)
         {
@@ -111,7 +117,7 @@ namespace Microsoft.Diagnostics.Tools.Counters
                 .AddCommand(MonitorCommand())
                 .AddCommand(CollectCommand())
                 .AddCommand(ListCommand())
-                .AddCommand(ProcessStatusCommand())
+                .AddCommand(ProcessStatusCommandHandler.ProcessStatusCommand("Lists the dotnet processes that can be monitored"))
                 .UseDefaults()
                 .Build();
             return parser.InvokeAsync(args);
index 4dc5bed68dcbb07d5229398d2fce7c0a12bc3e0f..7e9887f6bcd304009836a663ee43e341e43678ba 100644 (file)
@@ -12,6 +12,7 @@
 
   <ItemGroup>
     <Compile Include="$(MSBuildThisFileDirectory)..\dotnet-trace\Extensions.cs" Link="Extensions.cs" />
+    <Compile Include="..\Common\CommandExtensions.cs" Link="CommandExtensions.cs" />
     <Compile Include="..\Common\Commands\ProcessStatus.cs" Link="ProcessStatus.cs" />
   </ItemGroup>
 
index f560082ab518800957abc2324f12bfb4556b8c69..28209858d82335706880efdd501fb873b407017e 100644 (file)
@@ -76,7 +76,8 @@ namespace Microsoft.Diagnostics.Tools.Dump
                     // Run the commands from the dotnet-dump command line
                     if (command != null)
                     {
-                        foreach (string cmd in command) {
+                        foreach (string cmd in command)
+                        {
                             await _commandProcessor.Parse(cmd);
                         }
                     }
index bc258de370b58b4ea432615a07599ee57af58fff..7845d601f40134bfdb73e7a43e27b3ab0f3753ac 100644 (file)
@@ -59,7 +59,7 @@ namespace Microsoft.Diagnostics.Tools.Dump
         {
             try {
                 string arguments = null;
-                if (Arguments.Length > 0) {
+                if (Arguments != null && Arguments.Length > 0) {
                     arguments = string.Concat(Arguments.Select((arg) => arg + " "));
                 }
                 SOSHost.ExecuteCommand(AliasExpansion, arguments);
index c206bd3365e5cda9d6027c86fc37689ab2537341..117c73327c74aaa82fcef36af8f5bbaaa116c665 100644 (file)
@@ -2,13 +2,14 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
+using Microsoft.Diagnostics.NETCore.Client;
+using Microsoft.Internal.Common.Commands;
+using Microsoft.Tools.Common;
 using System.CommandLine;
 using System.CommandLine.Builder;
 using System.CommandLine.Invocation;
 using System.IO;
 using System.Threading.Tasks;
-using Microsoft.Diagnostics.NETCore.Client;
-using Microsoft.Internal.Common.Commands;
 
 namespace Microsoft.Diagnostics.Tools.Dump
 {
@@ -19,7 +20,7 @@ namespace Microsoft.Diagnostics.Tools.Dump
             var parser = new CommandLineBuilder()
                 .AddCommand(CollectCommand())
                 .AddCommand(AnalyzeCommand())
-                .AddCommand(ProcessStatusCommand())
+                .AddCommand(ProcessStatusCommandHandler.ProcessStatusCommand("Lists the dotnet processes that dumps can be collected"))
                 .UseDefaults()
                 .Build();
 
@@ -27,67 +28,74 @@ namespace Microsoft.Diagnostics.Tools.Dump
         }
 
         private static Command CollectCommand() =>
-            new Command(
-                "collect", 
-                "Capture dumps from a process", 
-                new Option[] { ProcessIdOption(), OutputOption(), DiagnosticLoggingOption(), TypeOption() },
-                handler: CommandHandler.Create<IConsole, int, string, bool, Dumper.DumpTypeOption>(new Dumper().Collect));
+            new Command( name: "collect", description: "Capture dumps from a process")
+            {
+                // Handler
+                CommandHandler.Create<IConsole, int, string, bool, Dumper.DumpTypeOption>(new Dumper().Collect),
+                // Options
+                ProcessIdOption(), OutputOption(), DiagnosticLoggingOption(), TypeOption()
+            };
 
         private static Option ProcessIdOption() =>
             new Option(
-                new[] { "-p", "--process-id" }, 
-                "The process to collect a memory dump from.",
-                new Argument<int> { Name = "pid" });
+                aliases: new[] { "-p", "--process-id" },
+                description: "The process id to collect a memory dump.")
+            {
+                Argument = new Argument<int>(name: "pid")
+            };
 
         private static Option OutputOption() =>
-            new Option(
-                new[] { "-o", "--output" },
-                @"The path where collected dumps should be written. Defaults to '.\dump_YYYYMMDD_HHMMSS.dmp' on Windows and 
-'./core_YYYYMMDD_HHMMSS' on Linux where YYYYMMDD is Year/Month/Day and HHMMSS is Hour/Minute/Second. Otherwise, it is the full
-path and file name of the dump.",
-                new Argument<string>() { Name = "output_dump_path" });
+            new Option( 
+                aliases: new[] { "-o", "--output" },
+                description: @"The path where collected dumps should be written. Defaults to '.\dump_YYYYMMDD_HHMMSS.dmp' on Windows and './core_YYYYMMDD_HHMMSS' 
+on Linux where YYYYMMDD is Year/Month/Day and HHMMSS is Hour/Minute/Second. Otherwise, it is the full path and file name of the dump.") 
+            {
+                Argument = new Argument<string>(name: "output_dump_path")
+            };
 
         private static Option DiagnosticLoggingOption() =>
             new Option(
-                new[] { "--diag" }, 
-                "Enable dump collection diagnostic logging.",
-                new Argument<bool> { Name = "diag" });
+                alias: "--diag", 
+                description: "Enable dump collection diagnostic logging.") 
+            {
+                Argument = new Argument<bool>(name: "diag")
+            };
 
         private static Option TypeOption() =>
             new Option(
-                "--type",
-                @"The dump type determines the kinds of information that are collected from the process. There are two types:
-
-heap - A large and relatively comprehensive dump containing module lists, thread lists, all stacks,
-       exception information, handle information, and all memory except for mapped images.
-mini - A small dump containing module lists, thread lists, exception information and all stacks.
-
-If not specified 'heap' is the default.",
-                new Argument<Dumper.DumpTypeOption>(Dumper.DumpTypeOption.Heap) { Name = "dump_type" });
+                alias: "--type",
+                description: @"The dump type determines the kinds of information that are collected from the process. There are two types: heap - A large and 
+relatively comprehensive dump containing module lists, thread lists, all stacks, exception information, handle information, and all memory except for mapped 
+images. mini - A small dump containing module lists, thread lists, exception information and all stacks. If not specified 'heap' is the default.")
+            {
+                Argument = new Argument<Dumper.DumpTypeOption>(name: "dump_type", defaultValue: Dumper.DumpTypeOption.Heap)
+            };
 
         private static Command AnalyzeCommand() =>
             new Command(
-                "analyze",
-                "Starts an interactive shell with debugging commands to explore a dump",
-                new Option[] { RunCommand() }, argument: DumpPath(),
-                handler: CommandHandler.Create<FileInfo, string[]>(new Analyzer().Analyze));
+                name: "analyze", 
+                description: "Starts an interactive shell with debugging commands to explore a dump")
+            {
+                // Handler
+                CommandHandler.Create<FileInfo, string[]>(new Analyzer().Analyze),
+                // Arguments and Options
+                DumpPath(),
+                RunCommand() 
+            };
 
         private static Argument DumpPath() =>
-            new Argument<FileInfo> {
-                Name = "dump_path",
-                Description = "Name of the dump file to analyze." }.ExistingOnly();
+            new Argument<FileInfo>(
+                name: "dump_path")
+            {
+                Description = "Name of the dump file to analyze."
+            }.ExistingOnly();
 
         private static Option RunCommand() =>
             new Option(
-                new[] { "-c", "--command" },
-                "Run the command on start.",
-                new Argument<string[]>() { Name = "command", Arity = ArgumentArity.ZeroOrMore });
-
-        private static Command ProcessStatusCommand() =>
-            new Command(
-                "ps",
-                "Display a list of dotnet processes to create dump from",
-                new Option[] { },
-                handler: CommandHandler.Create<IConsole>(ProcessStatusCommandHandler.PrintProcessStatus));
+                aliases: new[] { "-c", "--command" }, 
+                description: "Run the command on start.") 
+            {
+                Argument = new Argument<string[]>(name: "command", defaultValue: new string[0]) { Arity = ArgumentArity.ZeroOrMore }
+            };
     }
 }
index d93281273ebfca0d63fe5bc355cf4b3c16dbaaf4..831bca3e4adfc0135427f01338fd82f85538ae69 100644 (file)
@@ -18,6 +18,7 @@
   </ItemGroup>
 
   <ItemGroup>
+    <Compile Include="..\Common\CommandExtensions.cs" Link="CommandExtensions.cs" />
     <Compile Include="..\Common\Commands\ProcessStatus.cs" Link="ProcessStatus.cs" />
   </ItemGroup>
   
index 4be21afb8e88383218476a7695ffb69a9f7f81ed..67d01a66adc2d5722dce44ff29fd6c4e0835f1bf 100644 (file)
@@ -2,14 +2,11 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
+using Microsoft.Tools.Common;
 using System;
-using System.Collections.Generic;
 using System.CommandLine;
 using System.CommandLine.Binding;
-using System.CommandLine.Rendering;
-using System.Diagnostics;
 using System.IO;
-using System.Linq;
 using System.Threading;
 using System.Threading.Tasks;
 
@@ -100,42 +97,45 @@ namespace Microsoft.Diagnostics.Tools.GCDump
         public static Command CollectCommand() =>
             new Command(
                 name: "collect",
-                description: "Collects a diagnostic trace from a currently running process",
-                symbols: new Option[] {
-                    ProcessIdOption(),
-                    OutputPathOption(),
-                    VerboseOption(),
-                    TimeoutOption()
-                },
-                handler: HandlerDescriptor.FromDelegate((CollectDelegate)Collect).GetCommandHandler());
+                description: "Collects a diagnostic trace from a currently running process")
+            {
+                // Handler
+                HandlerDescriptor.FromDelegate((CollectDelegate)Collect).GetCommandHandler(),
+                // Options
+                ProcessIdOption(), OutputPathOption(), VerboseOption(), TimeoutOption() 
+            };
 
         public static Option ProcessIdOption() =>
             new Option(
                 aliases: new[] { "-p", "--process-id" },
-                description: "The process to collect the trace from",
-                argument: new Argument<int>(defaultValue: 0) { Name = "pid" },
-                isHidden: false);
+                description: "The process id to collect the trace.")
+            {
+                Argument = new Argument<int>(name: "pid", defaultValue: 0),
+            };
 
         private static Option OutputPathOption() =>
             new Option(
                 aliases: new[] { "-o", "--output" },
-                description:  $@"The path where collected gcdumps should be written. Defaults to '.\YYYYMMDD_HHMMSS_<pid>.gcdump' where YYYYMMDD is Year/Month/Day and HHMMSS is Hour/Minute/Second. Otherwise, it is the full path and file name of the dump.",
-                argument: new Argument<string>(defaultValue: "") { Name = "gcdump-file-path" },
-                isHidden: false);
+                description: $@"The path where collected gcdumps should be written. Defaults to '.\YYYYMMDD_HHMMSS_<pid>.gcdump' where YYYYMMDD is Year/Month/Day and HHMMSS is Hour/Minute/Second. Otherwise, it is the full path and file name of the dump.")
+            {
+                Argument = new Argument<string>(name: "gcdump-file-path", defaultValue: "")
+            };
 
         private static Option VerboseOption() =>
             new Option(
                 aliases: new[] { "-v", "--verbose" },
-                description: $"Output the log while collecting the gcdump",
-                argument: new Argument<bool>(defaultValue: false) { Name = "verbose" },
-                isHidden: false);
+                description: $"Output the log while collecting the gcdump.") 
+            {
+                Argument = new Argument<bool>(name: "verbose", defaultValue: false)
+            };
 
         private static int DefaultTimeout = 30;
         private static Option TimeoutOption() =>
             new Option(
                 aliases: new[] { "-t", "--timeout" },
-                description: $"Give up on collecting the gcdump if it takes longer than this many seconds. The default value is {DefaultTimeout}s",
-                argument: new Argument<int>(defaultValue: DefaultTimeout) { Name = "timeout" },
-                isHidden: false);
+                description: $"Give up on collecting the gcdump if it takes longer than this many seconds. The default value is {DefaultTimeout}s.")
+            {
+                Argument = new Argument<int>(name: "timeout", defaultValue: DefaultTimeout)
+            };
     }
 }
diff --git a/src/Tools/dotnet-gcdump/CommandLine/ProcessStatusCommandHandler.cs b/src/Tools/dotnet-gcdump/CommandLine/ProcessStatusCommandHandler.cs
deleted file mode 100644 (file)
index 4e15083..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using Microsoft.Internal.Common.Commands;
-using System;
-using System.CommandLine;
-using System.Threading.Tasks;
-
-namespace Microsoft.Diagnostics.Tools.GCDump
-{
-    internal static class ListProcessesCommandHandler
-    {
-        public static async Task<int> GetActivePorts(IConsole console)
-        {
-            ProcessStatusCommandHandler.PrintProcessStatus(console);
-            await Task.FromResult(0);
-            return 0;
-        }
-
-        public static Command ProcessStatusCommand() =>
-            new Command(
-                name: "ps",
-                description: "Lists dotnet processes that can be attached to.",
-                handler: System.CommandLine.Invocation.CommandHandler.Create<IConsole>(GetActivePorts),
-                isHidden: false);
-    }
-}
index 7bbba2fced011550e8355ef78351c8be95e16a4c..d2acd82bbe2a8f77682c868fa86b791cf67543cc 100644 (file)
@@ -2,6 +2,7 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
+using Microsoft.Internal.Common.Commands;
 using System.CommandLine.Builder;
 using System.CommandLine.Invocation;
 using System.Threading.Tasks;
@@ -14,7 +15,7 @@ namespace Microsoft.Diagnostics.Tools.GCDump
         {
             var parser = new CommandLineBuilder()
                 .AddCommand(CollectCommandHandler.CollectCommand())
-                .AddCommand(ListProcessesCommandHandler.ProcessStatusCommand())
+                .AddCommand(ProcessStatusCommandHandler.ProcessStatusCommand("Lists the dotnet processes that gcdumps can be collected"))
                 .UseDefaults()
                 .Build();
 
index 11d02c0a2a972cc3a1c8464707e4a6ac22a4355c..020f94233ca86c02308e777477343f3d15b5dcd4 100644 (file)
@@ -21,6 +21,7 @@
   </ItemGroup>
 
   <ItemGroup>
+    <Compile Include="..\Common\CommandExtensions.cs" Link="CommandExtensions.cs" />
     <Compile Include="..\Common\Commands\ProcessStatus.cs" Link="ProcessStatus.cs" />
   </ItemGroup>
 
index fa745dbe9c7a5b3d8921a9cb6763a94c92d5066b..c3d5f4917e7c83b45cb73d9f7314eaf4f0106869 100644 (file)
@@ -2,12 +2,11 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
+using Microsoft.Tools.Common;
 using SOS;
-using System;
 using System.CommandLine;
 using System.CommandLine.Builder;
 using System.CommandLine.Invocation;
-using System.Reflection;
 using System.Runtime.InteropServices;
 using System.Threading.Tasks;
 
@@ -28,22 +27,30 @@ namespace Microsoft.Diagnostics.Tools.SOS
 
         private static Command InstallCommand() =>
             new Command(
-                "install", 
-                "Installs SOS and configures LLDB to load it on startup.", 
-                new Option[] { ArchitectureOption() },
-                handler: CommandHandler.Create<IConsole, Architecture?>((console, architecture) => InvokeAsync(console, architecture, install: true)));
+                name: "install",
+                description: "Installs SOS and configures LLDB to load it on startup.")
+            {
+                // Handler
+                CommandHandler.Create<IConsole, Architecture?>((console, architecture) => InvokeAsync(console, architecture, install: true)),
+                // Options
+                ArchitectureOption()
+            };
 
         private static Option ArchitectureOption() =>
             new Option(
-                new[] { "--architecture" }, 
-                "The process to collect a memory dump from.",
-                new Argument<Architecture>() { Name = "architecture" });
+                alias: "--architecture",
+                description: "The processor architecture to install.")
+            {
+                Argument = new Argument<Architecture>(name: "architecture")
+            };
 
         private static Command UninstallCommand() =>
             new Command(
-                "uninstall",
-                "Uninstalls SOS and reverts any configuration changes to LLDB.",
-                handler: CommandHandler.Create<IConsole>((console) => InvokeAsync(console, architecture: null, install: false)));
+                name: "uninstall",
+                description: "Uninstalls SOS and reverts any configuration changes to LLDB.")
+            {
+                Handler = CommandHandler.Create<IConsole>((console) => InvokeAsync(console, architecture: null, install: false))
+            };
 
         private static Task<int> InvokeAsync(IConsole console, Architecture? architecture, bool install)
         {
index d38943b816f1f7f4c3fd5c78896754ee3bfa96c4..da59d34788bd75a9f6eba0cf6137d22a5bf37489 100644 (file)
@@ -9,6 +9,9 @@
     <PackageReleaseNotes>$(Description)</PackageReleaseNotes>
     <SOSPackagePathPrefix>tools/$(TargetFramework)/any</SOSPackagePathPrefix>
   </PropertyGroup>
+  <ItemGroup>
+    <Compile Include="..\Common\CommandExtensions.cs" Link="CommandExtensions.cs" />
+  </ItemGroup>
 
   <ItemGroup>
     <ProjectReference Include="$(MSBuildThisFileDirectory)..\..\SOS\SOS.InstallHelper\SOS.InstallHelper.csproj" />
index 41014bc5d23b7f17ece7d29d34c8f6c77a7f812b..298bc68244ad571b222521eaf3a4489b2222214c 100644 (file)
@@ -3,6 +3,7 @@
 // See the LICENSE file in the project root for more information.
 
 using Microsoft.Diagnostics.NETCore.Client;
+using Microsoft.Tools.Common;
 using System;
 using System.Collections.Generic;
 using System.CommandLine;
@@ -261,55 +262,63 @@ namespace Microsoft.Diagnostics.Tools.Trace
         public static Command CollectCommand() =>
             new Command(
                 name: "collect",
-                description: "Collects a diagnostic trace from a currently running process",
-                symbols: new Option[] {
-                    CommonOptions.ProcessIdOption(),
-                    CircularBufferOption(),
-                    OutputPathOption(),
-                    ProvidersOption(),
-                    ProfileOption(),
-                    CommonOptions.FormatOption(),
-                    DurationOption()
-                },
-                handler: HandlerDescriptor.FromDelegate((CollectDelegate)Collect).GetCommandHandler());
+                description: "Collects a diagnostic trace from a currently running process") 
+            {
+                // Handler
+                HandlerDescriptor.FromDelegate((CollectDelegate)Collect).GetCommandHandler(),
+                // Options
+                CommonOptions.ProcessIdOption(),
+                CircularBufferOption(),
+                OutputPathOption(),
+                ProvidersOption(),
+                ProfileOption(),
+                CommonOptions.FormatOption(),
+                DurationOption()
+            };
 
         private static uint DefaultCircularBufferSizeInMB => 256;
 
         private static Option CircularBufferOption() =>
             new Option(
                 alias: "--buffersize",
-                description: $"Sets the size of the in-memory circular buffer in megabytes. Default {DefaultCircularBufferSizeInMB} MB.",
-                argument: new Argument<uint>(defaultValue: DefaultCircularBufferSizeInMB) { Name = "size" },
-                isHidden: false);
+                description: $"Sets the size of the in-memory circular buffer in megabytes. Default {DefaultCircularBufferSizeInMB} MB.")
+            {
+                Argument = new Argument<uint>(name: "size", defaultValue: DefaultCircularBufferSizeInMB)
+            };
 
         public static string DefaultTraceName => "trace.nettrace";
 
         private static Option OutputPathOption() =>
             new Option(
                 aliases: new[] { "-o", "--output" },
-                description: $"The output path for the collected trace data. If not specified it defaults to '{DefaultTraceName}'",
-                argument: new Argument<FileInfo>(defaultValue: new FileInfo(DefaultTraceName)) { Name = "trace-file-path" },
-                isHidden: false);
+                description: $"The output path for the collected trace data. If not specified it defaults to '{DefaultTraceName}'.")
+            {
+                Argument = new Argument<FileInfo>(name: "trace-file-path", defaultValue: new FileInfo(DefaultTraceName))
+            };
 
         private static Option ProvidersOption() =>
             new Option(
                 alias: "--providers",
-                description: @"A list of EventPipe providers to be enabled. This is in the form 'Provider[,Provider]', where Provider is in the form: 'KnownProviderName[:Flags[:Level][:KeyValueArgs]]', and KeyValueArgs is in the form: '[key1=value1][;key2=value2]'. These providers are in addition to any providers implied by the --profile argument. If there is any discrepancy for a particular provider, the configuration here takes precedence over the implicit configuration from the profile.",
-                argument: new Argument<string>(defaultValue: "") { Name = "list-of-comma-separated-providers" }, // TODO: Can we specify an actual type?
-                isHidden: false);
+                description: @"A list of EventPipe providers to be enabled. This is in the form 'Provider[,Provider]', where Provider is in the form: 'KnownProviderName[:Flags[:Level][:KeyValueArgs]]', and KeyValueArgs is in the form: '[key1=value1][;key2=value2]'. These providers are in addition to any providers implied by the --profile argument. If there is any discrepancy for a particular provider, the configuration here takes precedence over the implicit configuration from the profile.")
+            {
+                Argument = new Argument<string>(name: "list-of-comma-separated-providers", defaultValue: "") // TODO: Can we specify an actual type?
+            };
 
         private static Option ProfileOption() =>
             new Option(
                 alias: "--profile",
-                description: @"A named pre-defined set of provider configurations that allows common tracing scenarios to be specified succinctly.",
-                argument: new Argument<string>(defaultValue: "") { Name = "profile-name" },
-                isHidden: false);
+                description: @"A named pre-defined set of provider configurations that allows common tracing scenarios to be specified succinctly.")
+            {
+                Argument = new Argument<string>(name: "profile-name", defaultValue: "")
+            };
 
         private static Option DurationOption() =>
             new Option(
                 alias: "--duration",
-                description: @"When specified, will trace for the given timespan and then automatically stop the trace. Provided in the form of dd:hh:mm:ss.",
-                argument: new Argument<TimeSpan>(defaultValue: default(TimeSpan)) { Name = "duration-timespan" },
-                isHidden: true);
+                description: @"When specified, will trace for the given timespan and then automatically stop the trace. Provided in the form of dd:hh:mm:ss.")
+            {
+                Argument = new Argument<TimeSpan>(name: "duration-timespan", defaultValue: default),
+                IsHidden = true
+            };
     }
 }
index ced5842d4bc1ac3ffe28c6448bf3f44551b6bf52..640ccb9f66e589a789270b97fecf5b7e37d5d844 100644 (file)
@@ -2,14 +2,11 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
-using Microsoft.Diagnostics.NETCore.Client;
+using Microsoft.Tools.Common;
 using System;
-using System.IO;
 using System.CommandLine;
 using System.CommandLine.Builder;
-using System.Diagnostics;
-using System.Linq;
-using System.Threading.Tasks;
+using System.IO;
 
 namespace Microsoft.Diagnostics.Tools.Trace
 {
@@ -45,25 +42,28 @@ namespace Microsoft.Diagnostics.Tools.Trace
         public static Command ConvertCommand() =>
             new Command(
                 name: "convert",
-                description: "Converts traces to alternate formats for use with alternate trace analysis tools. Can only convert from the nettrace format.",
-                argument: (new Argument<FileInfo>(defaultValue: new FileInfo(CollectCommandHandler.DefaultTraceName)) { 
-                    Name = "input-filename",
-                    Description = $"Input trace file to be converted.  Defaults to '{CollectCommandHandler.DefaultTraceName}'."
-                }).ExistingOnly(),
-                symbols: new Option[] {
-                    CommonOptions.ConvertFormatOption(),
-                    OutputOption()
-                },
-                handler: System.CommandLine.Invocation.CommandHandler.Create<IConsole, FileInfo, TraceFileFormat, FileInfo>(ConvertFile),
-                isHidden: false
-            );
+                description: "Converts traces to alternate formats for use with alternate trace analysis tools. Can only convert from the nettrace format")
+            {
+                // Handler
+                System.CommandLine.Invocation.CommandHandler.Create<IConsole, FileInfo, TraceFileFormat, FileInfo>(ConvertFile),
+                // Arguments and Options
+                InputFileArgument(),
+                CommonOptions.ConvertFormatOption(),
+                OutputOption(),
+            };
 
-        public static Option OutputOption() =>
+        private static Argument InputFileArgument() =>
+            new Argument<FileInfo>(name: "input-filename", defaultValue: new FileInfo(CollectCommandHandler.DefaultTraceName))
+            {
+                Description = $"Input trace file to be converted. Defaults to '{CollectCommandHandler.DefaultTraceName}'."
+            }.ExistingOnly();
+
+        private static Option OutputOption() =>
             new Option(
-                aliases: new [] { "-o", "--output" },
-                description: "Output filename. Extension of target format will be added.",
-                argument: new Argument<FileInfo>() { Name = "output-filename" },
-                isHidden: false
-            );
+                aliases: new[] { "-o", "--output" },
+                description: "Output filename. Extension of target format will be added.")
+            {
+                Argument = new Argument<FileInfo>(name: "output-filename")
+            };
     }
 }
diff --git a/src/Tools/dotnet-trace/CommandLine/Commands/ListProcessesCommandHandler.cs b/src/Tools/dotnet-trace/CommandLine/Commands/ListProcessesCommandHandler.cs
deleted file mode 100644 (file)
index c30ec69..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using Microsoft.Internal.Common.Commands;
-using System;
-using System.CommandLine;
-using System.Threading.Tasks;
-
-namespace Microsoft.Diagnostics.Tools.Trace
-{
-    internal static class ListProcessesCommandHandler
-    {
-        public static async Task<int> GetActivePorts(IConsole console)
-        {
-            ProcessStatusCommandHandler.PrintProcessStatus(console);
-            await Task.FromResult(0);
-            return 0;
-        }
-
-        public static Command ListProcessesCommand() =>
-            new Command(
-                name: "ps",
-                description: "Lists dotnet processes that can be attached to.",
-                handler: System.CommandLine.Invocation.CommandHandler.Create<IConsole>(GetActivePorts),
-                isHidden: false);
-    }
-}
index a182ae3f4a6abc8b57b14d0e1a51510ffecd520e..fd91811078f9ccf8e640070571f4e034d3431ae3 100644 (file)
@@ -35,9 +35,10 @@ namespace Microsoft.Diagnostics.Tools.Trace
         public static Command ListProfilesCommand() =>
             new Command(
                 name: "list-profiles",
-                description: "Lists pre-built tracing profiles with a description of what providers and filters are in each profile.",
-                handler: CommandHandler.Create<IConsole>(GetProfiles),
-                isHidden: false);
+                description: "Lists pre-built tracing profiles with a description of what providers and filters are in each profile")
+            {
+                Handler = CommandHandler.Create<IConsole>(GetProfiles),
+            };
 
         internal static IEnumerable<Profile> DotNETRuntimeProfiles { get; } = new[] {
             new Profile(
index 0584883938b058e836919e1c5bce362935c88e84..54715f21b66779e3e556e85ff2cd8e1a9feb466d 100644 (file)
@@ -3,8 +3,6 @@
 // See the LICENSE file in the project root for more information.
 
 using System.CommandLine;
-using System.IO;
-using System.Runtime.InteropServices;
 
 namespace Microsoft.Diagnostics.Tools.Trace
 {
@@ -13,24 +11,27 @@ namespace Microsoft.Diagnostics.Tools.Trace
         public static Option ProcessIdOption() =>
             new Option(
                 aliases: new[] { "-p", "--process-id" },
-                description: "The process to collect the trace from",
-                argument: new Argument<int> { Name = "pid" },
-                isHidden: false);
+                description: "The process id to collect the trace.")
+            {
+                Argument = new Argument<int>(name: "pid")
+            };
 
         public static TraceFileFormat DefaultTraceFileFormat => TraceFileFormat.NetTrace;
 
         public static Option FormatOption() =>
             new Option(
-                aliases: new[] { "--format" },
-                description: $"Sets the output format for the trace file.  Default is {DefaultTraceFileFormat}",
-                argument: new Argument<TraceFileFormat>(defaultValue: DefaultTraceFileFormat) { Name = "trace-file-format" },
-                isHidden: false);
+                alias: "--format",
+                description: $"Sets the output format for the trace file.  Default is {DefaultTraceFileFormat}.")
+            {
+                Argument = new Argument<TraceFileFormat>(name: "trace-file-format", defaultValue: DefaultTraceFileFormat)
+            };
 
         public static Option ConvertFormatOption() =>
             new Option(
-                aliases: new[] { "--format" },
-                description: $"Sets the output format for the trace file conversion.",
-                argument: new Argument<TraceFileFormat> { Name = "trace-file-format" },
-                isHidden: false);
+                alias: "--format",
+                description: $"Sets the output format for the trace file conversion.") 
+            {
+                Argument = new Argument<TraceFileFormat>(name: "trace-file-format")
+            };
     }
 }
index 606f7ae62c7782e303e313aa93e66bd5c0265d7e..ed01c52ea77f144f26d94af1bb396cd131ff8727 100644 (file)
@@ -2,6 +2,7 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
+using Microsoft.Internal.Common.Commands;
 using System.CommandLine.Builder;
 using System.CommandLine.Invocation;
 using System.Threading.Tasks;
@@ -14,7 +15,7 @@ namespace Microsoft.Diagnostics.Tools.Trace
         {
             var parser = new CommandLineBuilder()
                 .AddCommand(CollectCommandHandler.CollectCommand())
-                .AddCommand(ListProcessesCommandHandler.ListProcessesCommand())
+                .AddCommand(ProcessStatusCommandHandler.ProcessStatusCommand("Lists the dotnet processes that traces can be collected"))
                 .AddCommand(ListProfilesCommandHandler.ListProfilesCommand())
                 .AddCommand(ConvertCommandHandler.ConvertCommand())
                 .UseDefaults()
index 2f7e3713334e49a358f978ba7e010ab81c37b196..0739bc1ba9be4dbf86d6e97c05a6704284b2bb32 100644 (file)
@@ -20,6 +20,7 @@
   </ItemGroup>
 
   <ItemGroup>
+    <Compile Include="..\Common\CommandExtensions.cs" Link="CommandExtensions.cs" />
     <Compile Include="..\Common\Commands\ProcessStatus.cs" Link="ProcessStatus.cs" />
   </ItemGroup>