Redo command-line parsing, add -noninteractive and -encodedcommand options

This commit is contained in:
George Fleming committed 2016-04-14 09:09:52 -07:00
1 parent 7048b5774c
commit d1edcb38bd
1 file changed
+115 -38
+115 -38
View File
@@ -14,6 +14,30 @@ namespace Microsoft.PowerShell.CoreConsoleHost
public static class Program
{
private enum Options {Help, File, Command, NoProfile, NonInteractive, EncodedCommand, Invalid};
private class CommandOptions
{
public Options opt;
public string optString;
public CommandOptions(Options o, string s)
{
opt = o;
optString = s;
}
}
private static CommandOptions[] commandOptions = new CommandOptions[]
{
new CommandOptions(Options.Help, "help"),
new CommandOptions(Options.Help, "?"),
new CommandOptions(Options.File, "file"),
new CommandOptions(Options.Command, "command"),
new CommandOptions(Options.NoProfile, "noprofile"),
new CommandOptions(Options.NonInteractive, "noninteractive"),
new CommandOptions(Options.EncodedCommand, "encodedcommand")
};
/// <summary>
/// Creates and initiates the listener instance.
/// </summary>
@@ -25,6 +49,7 @@ namespace Microsoft.PowerShell.CoreConsoleHost
// here eliminates the need for a custom native host.
PowerShellAssemblyLoadContextInitializer.SetPowerShellAssemblyLoadContext(string.Empty);
// Argument parsing
string initialScript = null;
bool loadProfiles = true;
@@ -37,15 +62,33 @@ namespace Microsoft.PowerShell.CoreConsoleHost
bool hasNext = (i+1) < args.Length;
string nextArg = hasNext ? args[i+1] : string.Empty;
// --help was specified
if (arg == "--help" || arg == "-h")
// options start with "-" or "--"
string option;
if (arg.StartsWith("-"))
{
Console.WriteLine(@"
usage: powershell[.exe] [ (--help | -h) ]
if (arg.StartsWith("--"))
{
option = arg.Remove(0, 2);
}
else
{
option = arg.Remove(0, 1);
}
Options bestOption = FindOption(option);
switch (bestOption)
{
case Options.Help:
Console.WriteLine(@"
usage: powershell[.exe] [ (--help | -h | -?) ]
[ (--file | -f) <filePath> ]
[ <script>.ps1 ]
[ (--command | -c) <string> ]
[ --noprofile ]
[ --noprofile | -nop ]
[ --noninteractive | -non ]
[ (--encodedcommand | -e) <bas64Command> ]
SYNOPSIS
@@ -65,46 +108,63 @@ OPTIONS
(--command | -c) <string>
Will execute given string as a PowerShell script.
--noprofile
(--noprofile | -nop)
Disables parsing of PowerShell profiles.
(--help | -h)
(--help | -h | -?)
Prints this text.
(--noninteractive | -non)
Does not present an interactive prompt to the user.
(--encodedcommand | -e) <base64Command>
Accepts a base-64-encoded string version of a command.
");
return;
}
else if (arg == "--noprofile")
{
loadProfiles = false;
}
// lone argument is a script
else if (!hasNext && arg.EndsWith(".ps1"))
{
initialScript = Path.GetFullPath(arg);
}
// lone argument is an inline script
else if (!hasNext)
{
initialScript = arg;
}
// --file <filePath> was specified
else if (hasNext && (arg == "--file" || arg == "-f"))
{
initialScript = Path.GetFullPath(nextArg);
++i;
}
// --command <string> was specified
else if (hasNext && (arg == "--command" || arg == "-c"))
{
if (nextArg == "-")
{
initialScript = "\"TODO: read stdin using Console.OpenStandardInput\"";
return;
case Options.NoProfile:
loadProfiles = false;
break;
case Options.File:
initialScript = Path.GetFullPath(nextArg);
++i;
break;
case Options.Command:
if (nextArg == "-")
{
initialScript = "\"TODO: read stdin using Console.OpenStandardInput\"";
}
else
{
initialScript = nextArg;
}
++i;
break;
case Options.NonInteractive:
// TODO, figure out what this option does exactly
break;
case Options.EncodedCommand:
byte[] data = Convert.FromBase64String(nextArg);
initialScript = Encoding.UTF8.GetString(data);
++i;
break;
default:
Console.WriteLine("Invalid command-line option: {0}. Use '-help' option to get a list of valid options.");
return;
}
else
}
else // not an option parameter
{
// lone argument is a script
if (!hasNext && arg.EndsWith(".ps1"))
{
initialScript = nextArg;
initialScript = Path.GetFullPath(arg);
}
// lone argument is an inline script
else if (!hasNext)
{
initialScript = arg;
}
++i;
}
}
}
@@ -129,6 +189,23 @@ OPTIONS
// The exit code is set in the host by the MyHost.SetShouldExit() method.
System.Environment.Exit(listener.ExitCode);
}
private static Options FindOption(string option)
{
int matches = 0;
int index = -1;
for (int i=0; i<commandOptions.Length; ++i)
{
if (commandOptions[i].optString.StartsWith(option, StringComparison.OrdinalIgnoreCase))
{
matches++;
index = i;
}
}
return (matches == 1) ? commandOptions[index].opt : Options.Invalid;
}
}
internal class Listener