/// <summary> /// Runs the specified shell command with the specified arguments; if the command name or arguments are invalid, prints error and usage information. /// </summary> /// <param name="assembly">The assembly to search for the shell command.</param> /// <param name="commandName">The name of the command.</param> /// <param name="args">The arguments to the shell command.</param> /// <param name="index">The index in <paramref name="args"/> at which to start parsing the arguments.</param> /// <param name="options">The options to use.</param> /// <returns>The value of the <see cref="ShellCommand.ExitCode"/> property after the command finishes running, or -1 if the command could not be created.</returns> /// <exception cref="ArgumentNullException"> /// <paramref name="assembly"/>, <paramref name="args"/>, or <paramref name="options"/> is <see langword="null"/> /// </exception> /// <exception cref="ArgumentOutOfRangeException"><paramref name="index"/> does not fall inside the bounds of <paramref name="args"/>.</exception> /// <remarks> /// <para> /// If the command could not be found, a list of possible commands is written to <see cref="CreateShellCommandOptions.Out"/>. If an error occurs parsing the command's arguments, the error /// message is written to <see cref="CreateShellCommandOptions.Error"/>, and the shell command's usage information is written to <see cref="CreateShellCommandOptions.Out"/>. /// </para> /// <para> /// If the <see cref="CreateShellCommandOptions.Out"/> property or <see cref="CreateShellCommandOptions.Error"/> property is <see langword="null"/>, output /// is written to the standard output and error streams respectively, with line wrapping at word boundaries applied to the output, wrapping at the console's window width. When the console output is /// redirected to a file, Microsoft .Net will still report the console's actual window width, but on Mono the value of /// the <see cref="Console.WindowWidth"/> property will be 0. In that case, the usage information will not be wrapped. /// </para> /// <para> /// If the <see cref="CreateShellCommandOptions.Out"/> property or <see cref="CreateShellCommandOptions.Error"/> property are instance of the /// <see cref="LineWrappingTextWriter"/> class, this method indents additional lines for the usage syntax and argument descriptions according /// to the values specified by the <see cref="CreateShellCommandOptions"/>, unless the <see cref="LineWrappingTextWriter.MaximumLineLength"/> property is less than 30. /// </para> /// </remarks> public static int RunShellCommand(Assembly assembly, string commandName, string[] args, int index, CreateShellCommandOptions options) { ShellCommand command = CreateShellCommand(assembly, commandName, args, index, options); if (command != null) { command.Run(); return(command.ExitCode); } else { return(-1); } }
/// <summary> /// Finds and instantiates the shell command with the specified name, or if that fails, writes error and usage information to the specified writers. /// </summary> /// <param name="assembly">The assembly to search for the shell command.</param> /// <param name="commandName">The name of the command.</param> /// <param name="args">The arguments to the shell command.</param> /// <param name="index">The index in <paramref name="args"/> at which to start parsing the arguments.</param> /// <param name="options">The options to use.</param> /// <returns>An instance a class deriving from <see cref="ShellCommand"/>, or <see langword="null"/> if the command was not found or an error occurred parsing the arguments.</returns> /// <exception cref="ArgumentNullException"> /// <paramref name="assembly"/>, <paramref name="args"/>, or <paramref name="options"/> is <see langword="null"/> /// </exception> /// <exception cref="ArgumentOutOfRangeException"><paramref name="index"/> does not fall inside the bounds of <paramref name="args"/>.</exception> /// <remarks> /// <para> /// If the command could not be found, a list of possible commands is written to <see cref="CreateShellCommandOptions.Out"/>. If an error occurs parsing the command's arguments, the error /// message is written to <see cref="CreateShellCommandOptions.Error"/>, and the shell command's usage information is written to <see cref="CreateShellCommandOptions.Out"/>. /// </para> /// <para> /// If the <see cref="CreateShellCommandOptions.Out"/> property or <see cref="CreateShellCommandOptions.Error"/> property is <see langword="null"/>, output /// is written to the standard output and error streams respectively, with line wrapping at word boundaries applied to the output, wrapping at the console's window width. When the console output is /// redirected to a file, Microsoft .Net will still report the console's actual window width, but on Mono the value of /// the <see cref="Console.WindowWidth"/> property will be 0. In that case, the usage information will not be wrapped. /// </para> /// <para> /// If the <see cref="CreateShellCommandOptions.Out"/> property or <see cref="CreateShellCommandOptions.Error"/> property are instance of the /// <see cref="LineWrappingTextWriter"/> class, this method indents additional lines for the usage syntax and argument descriptions according /// to the values specified by the <see cref="CreateShellCommandOptions"/>, unless the <see cref="LineWrappingTextWriter.MaximumLineLength"/> property is less than 30. /// </para> /// </remarks> public static ShellCommand CreateShellCommand(Assembly assembly, string commandName, string[] args, int index, CreateShellCommandOptions options) { if (assembly == null) { throw new ArgumentNullException("assembly"); } if (args == null) { throw new ArgumentNullException("args"); } if (index < 0 || index > args.Length) { throw new ArgumentOutOfRangeException("index"); } if (options == null) { throw new ArgumentNullException("options"); } bool disposeOut = false; bool disposeError = false; TextWriter output = options.Out; TextWriter error = options.Error; try { if (output == null) { disposeOut = true; output = LineWrappingTextWriter.ForConsoleOut(); options.Out = output; } if (error == null) { disposeError = true; error = LineWrappingTextWriter.ForConsoleError(); options.Error = error; } Type commandType = commandName == null ? null : GetShellCommand(assembly, commandName, options.CommandNameComparer); if (commandType == null) { WriteShellCommandListUsage(output, assembly, options); } else if (CommandUsesCustomArgumentParsing(commandType)) { return((ShellCommand)Activator.CreateInstance(commandType, args, index, options)); } else { CommandLineParser parser = new CommandLineParser(commandType, options.ArgumentNamePrefixes, options.ArgumentNameComparer) { AllowDuplicateArguments = options.AllowDuplicateArguments, AllowWhiteSpaceValueSeparator = options.AllowWhiteSpaceValueSeparator, }; ShellCommand command = null; try { command = (ShellCommand)parser.Parse(args, index); } catch (CommandLineArgumentException ex) { error.WriteLine(ex.Message); error.WriteLine(); } if (command == null) { string originalPrefix = options.UsageOptions.UsagePrefix; options.UsageOptions.UsagePrefix += " " + GetShellCommandName(commandType); // If we're writing this to the console, output should already by a LineWrappingTextWriter, so the max line length argument here is ignored. parser.WriteUsage(output, 0, options.UsageOptions); options.UsageOptions.UsagePrefix = originalPrefix; } else { return(command); } } return(null); } finally { if (disposeOut && output != null) { output.Dispose(); } if (disposeError && error != null) { error.Dispose(); } } }