Skip to content

Commit 8ba4457

Browse files
committed
Add events for PromptForChoice and PromptForObject
Add sample handler for PromptForChoice to Demo project Switch to native Windows CredUI PromptForWindowsCredentials
1 parent 1a79f4a commit 8ba4457

10 files changed

+1888
-307
lines changed

PoshCode.PoshConsole/Controls/ConsoleControl.cs

+53-22
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
using System.Windows.Input;
1818
using System.Windows.Media;
1919
using System.Windows.Threading;
20+
using PoshCode.Interop;
21+
using PoshCode.Properties;
2022

2123
namespace PoshCode.Controls
2224
{
@@ -653,16 +655,26 @@ public string Title
653655
set { SetValue(TitleProperty, value); }
654656
}
655657

656-
657-
public Dictionary<string, PSObject> Prompt(string caption, string message, Collection<FieldDescription> descriptions)
658+
public event EventHandler<PromptForObjectEventArgs> PromptForObject;
659+
public Dictionary<string, PSObject> OnPromptForObject(PromptForObjectEventArgs e)
658660
{
659-
if (!string.IsNullOrEmpty(caption))
660-
Write(caption + "\n");
661-
if (!string.IsNullOrEmpty(message))
662-
Write(message + "\n");
661+
662+
EventHandler<PromptForObjectEventArgs> handler = PromptForObject;
663+
if (handler != null)
664+
{
665+
handler(this, e);
666+
return e.Results;
667+
}
668+
669+
670+
671+
if (!string.IsNullOrEmpty(e.Caption))
672+
Write(e.Caption + "\n");
673+
if (!string.IsNullOrEmpty(e.Message))
674+
Write(e.Message + "\n");
663675

664676
var results = new Dictionary<string, PSObject>();
665-
foreach (var fd in descriptions)
677+
foreach (var fd in e.Descriptions)
666678
{
667679
Type type = Type.GetType(fd.ParameterAssemblyFullName);
668680

@@ -675,7 +687,7 @@ public Dictionary<string, PSObject> Prompt(string caption, string message, Colle
675687
int count = 0;
676688
do
677689
{
678-
PSObject single = GetSingle(caption, message, string.Format("{0}[{1}]", prompt, count++),
690+
PSObject single = GetSingle(e.Caption, e.Message, $"{prompt}[{count++}]",
679691
fd.HelpMessage, fd.DefaultValue, type);
680692
if (single == null) break;
681693

@@ -690,7 +702,7 @@ public Dictionary<string, PSObject> Prompt(string caption, string message, Colle
690702
}
691703
else
692704
{
693-
results[fd.Name] = GetSingle(caption, message, prompt, fd.HelpMessage, fd.DefaultValue, type);
705+
results[fd.Name] = GetSingle(e.Caption, e.Message, prompt, fd.HelpMessage, fd.DefaultValue, type);
694706
}
695707

696708
}
@@ -700,7 +712,14 @@ private PSObject GetSingle(string caption, string message, string prompt, string
700712
{
701713
if (null != type && type == typeof(PSCredential))
702714
{
703-
return PSObject.AsPSObject(PromptForCredentialInline(caption, message, String.Empty, prompt));
715+
if (Settings.Default.UseCredentialUI)
716+
{
717+
return PSObject.AsPSObject(CredentialUI.Prompt(caption, message, psDefault.ToString(), string.Empty));
718+
}
719+
else
720+
{
721+
return PSObject.AsPSObject(PromptForCredentialInline(caption, message, psDefault.ToString(), prompt));
722+
}
704723
}
705724

706725
while (true)
@@ -765,14 +784,24 @@ private PSObject GetSingle(string caption, string message, string prompt, string
765784
}
766785
}
767786

768-
public int PromptForChoice(string caption, string message, Collection<ChoiceDescription> choices, int defaultChoice)
787+
788+
// public delegate void PromptForChoiceHandler(object sender, PromptForChoiceEventArgs e);
789+
public event EventHandler<PromptForChoiceEventArgs> PromptForChoice;
790+
public int OnPromptForChoice(PromptForChoiceEventArgs e)
769791
{
792+
EventHandler<PromptForChoiceEventArgs> handler = PromptForChoice;
793+
if (handler != null)
794+
{
795+
handler(this, e);
796+
return e.SelectedIndex;
797+
}
798+
770799
// Write the caption and message strings in Blue.
771-
Write(ConsoleColor.Blue, ConsoleColor.Black, caption + "\n" + message + "\n");
800+
Write(ConsoleColor.Blue, ConsoleColor.Black, e.Caption + "\n" + e.Message + "\n");
772801

773802
// Convert the choice collection into something that's a little easier to work with
774803
// See the BuildHotkeysAndPlainLabels method for details.
775-
var promptData = BuildHotkeysAndPlainLabels(choices, true);
804+
var promptData = BuildHotkeysAndPlainLabels(e.Choices, true);
776805

777806

778807
// Loop reading prompts until a match is made, the default is
@@ -781,9 +810,9 @@ public int PromptForChoice(string caption, string message, Collection<ChoiceDesc
781810
{
782811

783812
// Format the overall choice prompt string to display...
784-
for (int element = 0; element < promptData.GetLength(1); element++)
813+
for (var element = 0; element < promptData.GetLength(1); element++)
785814
{
786-
if (element == defaultChoice)
815+
if (element == e.SelectedIndex)
787816
{
788817
Write(ConsoleBrushes.VerboseForeground, ConsoleBrushes.VerboseBackground,
789818
$"[{promptData[0, element]}] {promptData[1, element]} ");
@@ -793,27 +822,27 @@ public int PromptForChoice(string caption, string message, Collection<ChoiceDesc
793822
Write(null, null, $"[{promptData[0, element]}] {promptData[1, element]} ");
794823
}
795824
}
796-
Write(null, null, $"(default is \"{promptData[0, defaultChoice]}\"):");
825+
Write(null, null, $"(default is \"{promptData[0, e.SelectedIndex]}\"):");
797826

798827
string data = ReadLine().Trim().ToUpper();
799828

800829
// If the choice string was empty, use the default selection.
801830
if (data.Length == 0)
802-
return defaultChoice;
831+
return e.SelectedIndex;
803832

804833
// See if the selection matched and return the
805834
// corresponding index if it did...
806-
for (int i = 0; i < choices.Count; i++)
835+
for (var i = 0; i < e.Choices.Count; i++)
807836
{
808837
if (promptData[0, i][0] == data[0])
809838
return i;
810839
}
811840

812841
// If they picked the very last thing in the list, they want help
813-
if (promptData.GetLength(1) > choices.Count && promptData[0, choices.Count] == data)
842+
if (promptData.GetLength(1) > e.Choices.Count && promptData[0, e.Choices.Count] == data)
814843
{
815844
// Show help
816-
foreach (var choice in choices)
845+
foreach (var choice in e.Choices)
817846
{
818847
Write($"{choice.Label.Replace("&", "")} - {choice.HelpMessage}\n");
819848
}
@@ -848,7 +877,8 @@ public PSCredential PromptForCredentialInline(string caption, string message, st
848877
do
849878
{
850879
fields = new Collection<FieldDescription>(new[] { user });
851-
var login = Prompt(caption, message, fields);
880+
var username = new PromptForObjectEventArgs(caption, message, fields);
881+
var login = OnPromptForObject(username);
852882
userName = login["User"].BaseObject as string;
853883
} while (userName != null && userName.Length == 0);
854884
}
@@ -870,7 +900,8 @@ public PSCredential PromptForCredentialInline(string caption, string message, st
870900
pass.IsMandatory = true;
871901

872902
fields = new Collection<FieldDescription>(new[] { pass });
873-
var password = Prompt(String.Empty, String.Empty, fields);
903+
var pwd = new PromptForObjectEventArgs(string.Empty, string.Empty, fields);
904+
var password = OnPromptForObject(pwd);
874905

875906
// TODO: I'm not sure what to do with the PSCredentialUIOptions options, because PowerShell.exe ignores them
876907
return new PSCredential(userName, (SecureString)password["Password"].BaseObject);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
using System;
2+
using System.Collections.ObjectModel;
3+
using System.Management.Automation.Host;
4+
5+
namespace PoshCode.Controls
6+
{
7+
public class PromptForChoiceEventArgs : EventArgs
8+
{
9+
public string Caption { get; set; }
10+
public string Message { get; set; }
11+
public Collection<ChoiceDescription> Choices { get; set; }
12+
public int SelectedIndex { get; set; }
13+
14+
public bool Handled { get; set; }
15+
16+
public PromptForChoiceEventArgs(string caption,
17+
string message,
18+
Collection<ChoiceDescription> choices,
19+
int selectedIndex)
20+
{
21+
Caption = caption;
22+
Message = message;
23+
Choices = choices;
24+
SelectedIndex = selectedIndex;
25+
}
26+
}
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Collections.ObjectModel;
4+
using System.Management.Automation;
5+
using System.Management.Automation.Host;
6+
7+
namespace PoshCode.Controls
8+
{
9+
public class PromptForObjectEventArgs : EventArgs
10+
{
11+
public string Caption { get; set; }
12+
public string Message { get; set; }
13+
public Collection<FieldDescription> Descriptions { get; set; }
14+
15+
public Dictionary<string, PSObject> Results { get; set; }
16+
17+
public PromptForObjectEventArgs(string caption, string message, Collection<FieldDescription> descriptions)
18+
{
19+
Caption = caption;
20+
Message = message;
21+
Descriptions = descriptions;
22+
Results = new Dictionary<string, PSObject>();
23+
}
24+
}
25+
}

0 commit comments

Comments
 (0)