From 4c1ee1c589a7fd050e09fbe06f6a691d50774c6c Mon Sep 17 00:00:00 2001 From: George Fleming Date: Thu, 14 Apr 2016 11:18:47 -0700 Subject: [PATCH] Prevent UI popups when run with -noninteractive --- .../host.cs | 2 +- .../main.cs | 17 +- .../ui.cs | 280 ++++++++++-------- 3 files changed, 166 insertions(+), 133 deletions(-) diff --git a/src/Microsoft.PowerShell.CoreConsoleHost/host.cs b/src/Microsoft.PowerShell.CoreConsoleHost/host.cs index 6d23885fd..c987abac7 100644 --- a/src/Microsoft.PowerShell.CoreConsoleHost/host.cs +++ b/src/Microsoft.PowerShell.CoreConsoleHost/host.cs @@ -16,7 +16,7 @@ namespace Microsoft.PowerShell.CoreConsoleHost public MyHost(Listener Listener) { this.Listener = Listener; - this.myHostUserInterface = new MyHostUserInterface(Listener.HasUI); + this.myHostUserInterface = new MyHostUserInterface(Listener.HasUI, Listener.Interactive); } /// diff --git a/src/Microsoft.PowerShell.CoreConsoleHost/main.cs b/src/Microsoft.PowerShell.CoreConsoleHost/main.cs index aa6818714..d01f7a54d 100644 --- a/src/Microsoft.PowerShell.CoreConsoleHost/main.cs +++ b/src/Microsoft.PowerShell.CoreConsoleHost/main.cs @@ -53,6 +53,7 @@ namespace Microsoft.PowerShell.CoreConsoleHost // Argument parsing string initialScript = null; bool loadProfiles = true; + bool interactive = true; if (args.Length > 0) { @@ -141,7 +142,7 @@ OPTIONS ++i; break; case Options.NonInteractive: - // TODO, figure out what this option does exactly + interactive = false; break; case Options.EncodedCommand: byte[] data = Convert.FromBase64String(nextArg); @@ -174,7 +175,7 @@ OPTIONS ConsoleColor InitialBackgroundColor = Console.BackgroundColor; // Create the listener and run it - Listener listener = new Listener(initialScript, loadProfiles); + Listener listener = new Listener(initialScript, loadProfiles, interactive); // only run if there was no script file passed in if (initialScript == null) @@ -282,13 +283,19 @@ OPTIONS } /// - /// Gets or sets a value indicating whether UI should exit. + /// Gets or sets a value indicating whether UI exists (display prompt) /// public bool HasUI; - public Listener(string initialScript, bool loadProfiles) + /// + /// Gets or sets a value indicating whether session is interactive (allow popup) + /// + public bool Interactive; + + public Listener(string initialScript, bool loadProfiles, bool interactive) { - HasUI = (initialScript == null) ? true : false; + this.HasUI = (initialScript == null) ? true : false; + this.Interactive = interactive; // Create the host and runspace instances for this interpreter. // Note that this application does not support console files so diff --git a/src/Microsoft.PowerShell.CoreConsoleHost/ui.cs b/src/Microsoft.PowerShell.CoreConsoleHost/ui.cs index 14667eee1..05d02188d 100644 --- a/src/Microsoft.PowerShell.CoreConsoleHost/ui.cs +++ b/src/Microsoft.PowerShell.CoreConsoleHost/ui.cs @@ -20,7 +20,7 @@ namespace Microsoft.PowerShell.CoreConsoleHost /// /// Public constructor /// - public MyHostUserInterface(bool hasUI) + public MyHostUserInterface(bool hasUI, bool interactive) { myRawUi = (hasUI) ? new MyRawUserInterface() : null; } @@ -39,6 +39,11 @@ namespace Microsoft.PowerShell.CoreConsoleHost get { return this.myRawUi; } } + /// + /// Whether user pop-ups are allowed + /// + public bool Interactive; + /// /// Prompts the user for input. /// The caption or title of the prompt. @@ -52,26 +57,33 @@ namespace Microsoft.PowerShell.CoreConsoleHost string message, Collection descriptions) { - this.Write( - ConsoleColor.White, - Console.BackgroundColor, - caption + System.Environment.NewLine + message + " "); - Dictionary results = - new Dictionary(); - foreach (FieldDescription fd in descriptions) + if (Interactive) { - string[] label = GetHotkeyAndLabel(fd.Label); - this.WriteLine(label[1]); - string userData = Console.ReadLine(); - if (userData == null) + this.Write( + ConsoleColor.White, + Console.BackgroundColor, + caption + System.Environment.NewLine + message + " "); + Dictionary results = + new Dictionary(); + foreach (FieldDescription fd in descriptions) { - return null; + string[] label = GetHotkeyAndLabel(fd.Label); + this.WriteLine(label[1]); + string userData = Console.ReadLine(); + if (userData == null) + { + return null; + } + + results[fd.Name] = PSObject.AsPSObject(userData); } - results[fd.Name] = PSObject.AsPSObject(userData); + return results; + } + else + { + throw new InvalidOperationException("Cannot prompt user when invoked with --noninteractive option."); } - - return results; } /// @@ -93,57 +105,64 @@ namespace Microsoft.PowerShell.CoreConsoleHost Collection choices, int defaultChoice) { - // Write the caption and message strings in Blue. - this.WriteLine( - ConsoleColor.Blue, - Console.BackgroundColor, - caption + System.Environment.NewLine + message + System.Environment.NewLine); - - // Convert the choice collection into something that is - // easier to work with. See the BuildHotkeysAndPlainLabels - // method for details. - string[,] promptData = BuildHotkeysAndPlainLabels(choices); - - // Format the overall choice prompt string to display. - StringBuilder sb = new StringBuilder(); - for (int element = 0; element < choices.Count; element++) + if (Interactive) { + // Write the caption and message strings in Blue. + this.WriteLine( + ConsoleColor.Blue, + Console.BackgroundColor, + caption + System.Environment.NewLine + message + System.Environment.NewLine); + + // Convert the choice collection into something that is + // easier to work with. See the BuildHotkeysAndPlainLabels + // method for details. + string[,] promptData = BuildHotkeysAndPlainLabels(choices); + + // Format the overall choice prompt string to display. + StringBuilder sb = new StringBuilder(); + for (int element = 0; element < choices.Count; element++) + { + sb.Append(String.Format( + CultureInfo.CurrentCulture, + "|{0}> {1} ", + promptData[0, element], + promptData[1, element])); + } + sb.Append(String.Format( - CultureInfo.CurrentCulture, - "|{0}> {1} ", - promptData[0, element], - promptData[1, element])); - } + CultureInfo.CurrentCulture, + "[Default is ({0}]", + promptData[0, defaultChoice])); - sb.Append(String.Format( - CultureInfo.CurrentCulture, - "[Default is ({0}]", - promptData[0, defaultChoice])); - - // Read prompts until a match is made, the default is - // chosen, or the loop is interrupted with ctrl-C. - while (true) - { - this.WriteLine(ConsoleColor.Cyan, Console.BackgroundColor, sb.ToString()); - string data = Console.ReadLine().Trim().ToUpper(); - - // If the choice string was empty, use the default selection. - if (data.Length == 0) + // Read prompts until a match is made, the default is + // chosen, or the loop is interrupted with ctrl-C. + while (true) { - return defaultChoice; - } + this.WriteLine(ConsoleColor.Cyan, Console.BackgroundColor, sb.ToString()); + string data = Console.ReadLine().Trim().ToUpper(); - // See if the selection matched and return the - // corresponding index if it did. - for (int i = 0; i < choices.Count; i++) - { - if (promptData[0, i] == data) + // If the choice string was empty, use the default selection. + if (data.Length == 0) { - return i; + return defaultChoice; } - } - this.WriteErrorLine("Invalid choice: " + data); + // See if the selection matched and return the + // corresponding index if it did. + for (int i = 0; i < choices.Count; i++) + { + if (promptData[0, i] == data) + { + return i; + } + } + + this.WriteErrorLine("Invalid choice: " + data); + } + } + else + { + throw new InvalidOperationException("Cannot prompt user when invoked with --noninteractive option."); } } @@ -167,87 +186,94 @@ namespace Microsoft.PowerShell.CoreConsoleHost Collection choices, IEnumerable defaultChoices) { - // Write the caption and message strings in Blue. - this.WriteLine( - ConsoleColor.Blue, - Console.BackgroundColor, - caption + System.Environment.NewLine + message + System.Environment.NewLine); - - // Convert the choice collection into something that is - // easier to work with. See the BuildHotkeysAndPlainLabels - // method for details. - string[,] promptData = BuildHotkeysAndPlainLabels(choices); - - // Format the overall choice prompt string to display. - StringBuilder sb = new StringBuilder(); - for (int element = 0; element < choices.Count; element++) + if (Interactive) { - sb.Append(String.Format( - CultureInfo.CurrentCulture, - "|{0}> {1} ", - promptData[0, element], - promptData[1, element])); - } + // Write the caption and message strings in Blue. + this.WriteLine( + ConsoleColor.Blue, + Console.BackgroundColor, + caption + System.Environment.NewLine + message + System.Environment.NewLine); - Collection defaultResults = new Collection(); - if (defaultChoices != null) - { - int countDefaults = 0; - foreach (int defaultChoice in defaultChoices) + // Convert the choice collection into something that is + // easier to work with. See the BuildHotkeysAndPlainLabels + // method for details. + string[,] promptData = BuildHotkeysAndPlainLabels(choices); + + // Format the overall choice prompt string to display. + StringBuilder sb = new StringBuilder(); + for (int element = 0; element < choices.Count; element++) { - ++countDefaults; - defaultResults.Add(defaultChoice); + sb.Append(String.Format( + CultureInfo.CurrentCulture, + "|{0}> {1} ", + promptData[0, element], + promptData[1, element])); } - if (countDefaults != 0) + Collection defaultResults = new Collection(); + if (defaultChoices != null) { - sb.Append(countDefaults == 1 ? "[Default choice is " : "[Default choices are "); + int countDefaults = 0; foreach (int defaultChoice in defaultChoices) { - sb.AppendFormat( - CultureInfo.CurrentCulture, - "\"{0}\",", - promptData[0, defaultChoice]); + ++countDefaults; + defaultResults.Add(defaultChoice); } - sb.Remove(sb.Length - 1, 1); - sb.Append("]"); + if (countDefaults != 0) + { + sb.Append(countDefaults == 1 ? "[Default choice is " : "[Default choices are "); + foreach (int defaultChoice in defaultChoices) + { + sb.AppendFormat( + CultureInfo.CurrentCulture, + "\"{0}\",", + promptData[0, defaultChoice]); + } + + sb.Remove(sb.Length - 1, 1); + sb.Append("]"); + } + } + + this.WriteLine( + ConsoleColor.Cyan, + Console.BackgroundColor, + sb.ToString()); + // Read prompts until a match is made, the default is + // chosen, or the loop is interrupted with ctrl-C. + Collection results = new Collection(); + while (true) + { + ReadNext: + string prompt = string.Format(CultureInfo.CurrentCulture, "Choice[{0}]:", results.Count); + this.Write(ConsoleColor.Cyan, Console.BackgroundColor, prompt); + string data = Console.ReadLine().Trim().ToUpper(); + + // If the choice string was empty, no more choices have been made. + // If there were no choices made, return the defaults + if (data.Length == 0) + { + return (results.Count == 0) ? defaultResults : results; + } + + // See if the selection matched and return the + // corresponding index if it did. + for (int i = 0; i < choices.Count; i++) + { + if (promptData[0, i] == data) + { + results.Add(i); + goto ReadNext; + } + } + + this.WriteErrorLine("Invalid choice: " + data); } } - - this.WriteLine( - ConsoleColor.Cyan, - Console.BackgroundColor, - sb.ToString()); - // Read prompts until a match is made, the default is - // chosen, or the loop is interrupted with ctrl-C. - Collection results = new Collection(); - while (true) + else { -ReadNext: - string prompt = string.Format(CultureInfo.CurrentCulture, "Choice[{0}]:", results.Count); - this.Write(ConsoleColor.Cyan, Console.BackgroundColor, prompt); - string data = Console.ReadLine().Trim().ToUpper(); - - // If the choice string was empty, no more choices have been made. - // If there were no choices made, return the defaults - if (data.Length == 0) - { - return (results.Count == 0) ? defaultResults : results; - } - - // See if the selection matched and return the - // corresponding index if it did. - for (int i = 0; i < choices.Count; i++) - { - if (promptData[0, i] == data) - { - results.Add(i); - goto ReadNext; - } - } - - this.WriteErrorLine("Invalid choice: " + data); + throw new InvalidOperationException("Cannot prompt user when invoked with --noninteractive option."); } }