/// <summary> /// Run command on <paramref name="type"/> and return exit code of executed command. /// </summary> /// <param name="type">Type to look for commands on.</param> /// <param name="arguments">List of command line arguments. First positional parameter is treated as command's name.</param> /// <param name="defaultCommandName">Default command name if no command name is specified as first parameter of <paramref name="arguments"/>.</param> /// <returns>Exit code of command-or-<see cref="DotNetExceptionExitCode"/> if exception happened-or-<see cref="BindFailureExitCode"/> if command not found and description is shown.</returns> public static int Run(Type type, CommandLineArguments arguments, string defaultCommandName = null) { if (type == null) { throw new ArgumentNullException("type"); } if (arguments == null) { throw new ArgumentNullException("arguments"); } try { var bindResult = BindMethod(type, defaultCommandName, arguments); if (bindResult.IsSuccess) { return((int)bindResult.Method.Invoke(null, bindResult.Arguments)); } else { var bestMatchMethod = (from bindingKeyValue in bindResult.FailedMethodBindings let parameters = bindingKeyValue.Value let method = bindingKeyValue.Key orderby parameters.Count(parameter => parameter.IsSuccess) descending select method).FirstOrDefault(); var error = default(CommandLineException); if (bestMatchMethod == null) { error = CommandLineException.CommandNotFound(bindResult.MethodName); } else { error = CommandLineException.InvalidCommandParameters(bestMatchMethod, bindResult.FailedMethodBindings[bestMatchMethod]); } if (DescribeOnBindFailure) { if (bindResult.MethodName == UnknownMethodName) { Console.WriteLine(" Error:"); Console.WriteLine(" No command is specified."); Console.WriteLine(); if (WriteWholeErrorMessageOnBindFailure) { Console.Error.WriteLine(error); Console.Error.WriteLine(); } Describe(type); } else if (bestMatchMethod != null) { Console.WriteLine(" Error:"); Console.WriteLine(string.Format(" Invalid parameters specified for '{0}' command.", bindResult.MethodName)); Console.WriteLine(); if (WriteWholeErrorMessageOnBindFailure) { Console.Error.WriteLine(error); Console.Error.WriteLine(); } Describe(type, bindResult.MethodName); } else { Console.WriteLine(" Error:"); Console.WriteLine(error.Message); Console.WriteLine(); } } else { throw error; } } return(BindFailureExitCode); } catch (Exception exception) { var handler = UnhandledException ?? DefaultUnhandledExceptionHandler; handler(null, new ExceptionEventArgs(exception)); return(DotNetExceptionExitCode); } }
internal static CommandLineException InvalidCommandParameters(MethodInfo commandMethod, ParameterBindResult[] parameterBindResults) { if (commandMethod == null) { throw new ArgumentNullException("commandMethod"); } if (parameterBindResults == null) { throw new ArgumentNullException("parameterBindResults"); } var bindingErrors = new Dictionary <string, Exception>(); var builder = new StringBuilder(); builder.AppendFormat("Invalid parameters for command {0}(", commandMethod.Name); foreach (var parameterBindResult in parameterBindResults) { if (parameterBindResult.Parameter.IsOptional) { builder.Append("["); } builder.Append(parameterBindResult.Parameter.Name); if (parameterBindResult.Parameter.IsOptional) { builder.Append("]"); } var isLast = parameterBindResult == parameterBindResults[parameterBindResults.Length - 1]; if (isLast) { builder.Append(")"); } else { builder.Append(", "); } } builder.AppendLine(":"); foreach (var parameterBindResult in parameterBindResults) { builder.Append("\t").Append(parameterBindResult.Parameter.Name).Append(": "); if (parameterBindResult.IsSuccess) { var value = TypeConvert.ToString(parameterBindResult.Value) ?? "<null>"; if (value.Length > 32) { builder.Append(value.Substring(0, 32)).AppendLine("..."); } else { builder.AppendLine(value); } } else { bindingErrors[parameterBindResult.Parameter.Name] = parameterBindResult.Error; var errorMessage = parameterBindResult.Error.Message; var parameterType = parameterBindResult.Parameter.ParameterType; parameterType = Nullable.GetUnderlyingType(parameterType) ?? parameterType; builder.Append("(").Append(parameterType.Name).Append(") "); if (parameterBindResult.Error is FormatException && parameterBindResult.Value != null) { var value = TypeConvert.ToString(parameterBindResult.Value) ?? "<null>"; builder.Append(errorMessage) .Append(" Value: '"); if (value.Length > 32) { builder.Append(value.Substring(0, 32)).Append("..."); } else { builder.Append(value); } builder.AppendLine("'."); } else { builder.AppendLine(errorMessage); } } } var error = new CommandLineException(builder.ToString()); error.Data["method"] = commandMethod.Name; #if !NETSTANDARD1_3 error.Data["methodToken"] = commandMethod.MetadataToken; #endif error.Data["bindingErrors"] = bindingErrors; return(error); }