Prompt(string caption, string message, Collection<FieldDescription> descriptions)
        {
            // Need to implement EchoOnPrompt
            HandleThrowOnReadAndPrompt();

            if (descriptions == null)
            {
                throw PSTraceSource.NewArgumentNullException("descriptions");
            }

            if (descriptions.Count < 1)
            {
                throw PSTraceSource.NewArgumentException("descriptions",
                    ConsoleHostUserInterfaceStrings.PromptEmptyDescriptionsErrorTemplate, "descriptions");
            }

            // we lock here so that multiple threads won't interleave the various reads and writes here.

            lock (_instanceLock)
            {
                Dictionary<string, PSObject> results = new Dictionary<string, PSObject>();

                Boolean cancelInput = false;

                if (!String.IsNullOrEmpty(caption))
                {
                    // Should be a skin lookup

                    WriteLineToConsole();
                    WriteToConsole(PromptColor, RawUI.BackgroundColor, WrapToCurrentWindowWidth(caption));
                    WriteLineToConsole();
                }
                if (!String.IsNullOrEmpty(message))
                {
                    WriteLineToConsole(WrapToCurrentWindowWidth(message));
                }

                if (AtLeastOneHelpMessageIsPresent(descriptions))
                {
                    WriteLineToConsole(WrapToCurrentWindowWidth(ConsoleHostUserInterfaceStrings.PromptHelp));
                }

                int descIndex = -1;

                foreach (FieldDescription desc in descriptions)
                {
                    descIndex++;
                    if (desc == null)
                    {
                        throw PSTraceSource.NewArgumentException("descriptions",
                            ConsoleHostUserInterfaceStrings.NullErrorTemplate,
                            string.Format(CultureInfo.InvariantCulture, "descriptions[{0}]", descIndex));
                    }
                    PSObject inputPSObject = null;
                    string fieldPrompt = null;
                    fieldPrompt = desc.Name;

                    bool fieldEchoOnPrompt = true;

                    // FieldDescription.ParameterAssemblyFullName never returns null. But this is
                    // defense in depth.
                    if (string.IsNullOrEmpty(desc.ParameterAssemblyFullName))
                    {
                        string paramName =
                            string.Format(CultureInfo.InvariantCulture, "descriptions[{0}].AssemblyFullName", descIndex);
                        throw PSTraceSource.NewArgumentException(paramName, ConsoleHostUserInterfaceStrings.NullOrEmptyErrorTemplate, paramName);
                    }

                    Type fieldType = InternalHostUserInterface.GetFieldType(desc);
                    if (fieldType == null)
                    {
                        if (InternalHostUserInterface.IsSecuritySensitiveType(desc.ParameterTypeName))
                        {
                            string errMsg =
                                StringUtil.Format(ConsoleHostUserInterfaceStrings.PromptTypeLoadErrorTemplate,
                                    desc.Name, desc.ParameterTypeFullName);
                            PromptingException e = new PromptingException(errMsg,
                                null, "BadTypeName", ErrorCategory.InvalidType);
                            throw e;
                        }

                        fieldType = typeof(string);
                    }

                    if (fieldType.GetInterface(typeof(IList).FullName) != null)
                    {
                        // field is a type implementing IList
                        ArrayList inputList = new ArrayList(); // stores all converted user input before
                        // assigned to an array

                        // if the field is an array, the element type can be found; else, use Object
                        Type elementType = typeof(Object);
                        if (fieldType.IsArray)
                        {
                            elementType = fieldType.GetElementType();
                            int rank = fieldType.GetArrayRank();
                            // This check may be redundant because it doesn't seem possible to create
                            // an array of zero dimension.
                            if (rank <= 0)
                            {
                                string msg = StringUtil.Format(ConsoleHostUserInterfaceStrings.RankZeroArrayErrorTemplate, desc.Name);
                                ArgumentException innerException = PSTraceSource.NewArgumentException(
                                    string.Format(CultureInfo.InvariantCulture,
                                    "descriptions[{0}].AssemblyFullName", descIndex));
                                PromptingException e = new PromptingException(msg, innerException, "ZeroRankArray", ErrorCategory.InvalidOperation);
                                throw e;
                            }
                        }

                        StringBuilder fieldPromptList = new StringBuilder(fieldPrompt);
                        // fieldPromptList = fieldPrompt + "[i] :"
                        fieldPromptList.Append("[");

                        while (true)
                        {
                            fieldPromptList.Append(
                                string.Format(CultureInfo.InvariantCulture, "{0}]: ", inputList.Count));
                            Boolean inputListEnd = false;
                            Object convertedObj = null;
                            string inputString = PromptForSingleItem(elementType, fieldPromptList.ToString(), fieldPrompt, caption, message,
                                desc, fieldEchoOnPrompt, true, out inputListEnd, out cancelInput, out convertedObj);

                            if (cancelInput || inputListEnd)
                            {
                                break;
                            }
                            else if (!cancelInput)
                            {
                                inputList.Add(convertedObj);
                                // Remove the indices from the prompt
                                fieldPromptList.Length = fieldPrompt.Length + 1;
                            }
                        }
                        // if cancelInput, should throw OperationCancelException?
                        if (!cancelInput)
                        {
                            object tryConvertResult = null;
                            if (LanguagePrimitives.TryConvertTo(inputList, fieldType, out tryConvertResult))
                            {
                                inputPSObject = PSObject.AsPSObject(tryConvertResult);
                            }
                            else
                            {
                                inputPSObject = PSObject.AsPSObject(inputList);
                            }
                        }
                    }
                    else
                    {
                        string printFieldPrompt = StringUtil.Format(ConsoleHostUserInterfaceStrings.PromptFieldPromptInputSeparatorTemplate,
                            fieldPrompt);
                        // field is not a list
                        Object convertedObj = null;
                        Boolean dummy = false;

                        PromptForSingleItem(fieldType, printFieldPrompt, fieldPrompt, caption, message, desc,
                                            fieldEchoOnPrompt, false, out dummy, out cancelInput, out convertedObj);
                        if (!cancelInput)
                        {
                            inputPSObject = PSObject.AsPSObject(convertedObj);
                        }
                    }
                    if (cancelInput)
                    {
                        s_tracer.WriteLine("Prompt canceled");
                        WriteLineToConsole();
                        results.Clear();
                        break;
                    }
                    results.Add(desc.Name, PSObject.AsPSObject(inputPSObject));
                }
                return results;
            }
        }
Пример #2
0
		public Collection<int> PromptForChoice(string caption, string message, Collection<ChoiceDescription> choices, IEnumerable<int> defaultChoices)
		{
			ConsoleHostUserInterface.ReadLineResult readLineResult = ConsoleHostUserInterface.ReadLineResult.endedOnEnter;
			Collection<int> nums;
			this.HandleThrowOnReadAndPrompt();
			if (choices != null)
			{
				if (choices.Count != 0)
				{
					Dictionary<int, bool> nums1 = new Dictionary<int, bool>();
					if (defaultChoices != null)
					{
						foreach (int defaultChoice in defaultChoices)
						{
							if (defaultChoice < 0 || defaultChoice >= choices.Count)
							{
								object[] objArray = new object[3];
								objArray[0] = "defaultChoice";
								objArray[1] = "choices";
								objArray[2] = defaultChoice;
								throw PSTraceSource.NewArgumentOutOfRangeException("defaultChoice", defaultChoice, "ConsoleHostUserInterfaceStrings", "InvalidDefaultChoiceForMultipleSelection", objArray);
							}
							else
							{
								if (nums1.ContainsKey(defaultChoice))
								{
									continue;
								}
								nums1.Add(defaultChoice, true);
							}
						}
					}
					Collection<int> nums2 = new Collection<int>();
					lock (this.instanceLock)
					{
						if (!string.IsNullOrEmpty(caption))
						{
							this.WriteLineToConsole();
							this.WriteToConsole(this.PromptColor, this.RawUI.BackgroundColor, this.WrapToCurrentWindowWidth(caption));
							this.WriteLineToConsole();
						}
						if (!string.IsNullOrEmpty(message))
						{
							this.WriteLineToConsole(this.WrapToCurrentWindowWidth(message));
						}
						string[,] strArrays = null;
						HostUIHelperMethods.BuildHotkeysAndPlainLabels(choices, out strArrays);
						this.WriteChoicePrompt(strArrays, nums1, true);
						if (nums1.Count > 0)
						{
							this.WriteLineToConsole();
						}
						int num = 0;
						while (true)
						{
							string str = StringUtil.Format(ConsoleHostUserInterfaceStrings.ChoiceMessage, num);
							this.WriteToConsole(this.PromptColor, this.RawUI.BackgroundColor, this.WrapToCurrentWindowWidth(str));
							string str1 = this.ReadLine(false, "", out readLineResult, true, true);
							if (readLineResult == ConsoleHostUserInterface.ReadLineResult.endedOnBreak)
							{
								string promptCanceledError = ConsoleHostUserInterfaceStrings.PromptCanceledError;
								PromptingException promptingException = new PromptingException(promptCanceledError, null, "PromptForChoiceCanceled", ErrorCategory.OperationStopped);
								throw promptingException;
							}
							if (str1.Length == 0)
							{
								break;
							}
							if (str1.Trim() != "?")
							{
								int num1 = HostUIHelperMethods.DetermineChoicePicked(str1.Trim(), choices, strArrays);
								if (num1 >= 0)
								{
									nums2.Add(num1);
									num++;
								}
							}
							else
							{
								this.ShowChoiceHelp(choices, strArrays);
							}
						}
						if (nums2.Count == 0 && nums1.Keys.Count >= 0)
						{
							foreach (int key in nums1.Keys)
							{
								nums2.Add(key);
							}
						}
						nums = nums2;
					}
					return nums;
				}
				else
				{
					object[] objArray1 = new object[1];
					objArray1[0] = "choices";
					throw PSTraceSource.NewArgumentException("choices", "ConsoleHostUserInterfaceStrings", "EmptyChoicesErrorTemplate", objArray1);
				}
			}
			else
			{
				throw PSTraceSource.NewArgumentNullException("choices");
			}
		}
Пример #3
0
		public override int PromptForChoice(string caption, string message, Collection<ChoiceDescription> choices, int defaultChoice)
		{
			ConsoleHostUserInterface.ReadLineResult readLineResult = ConsoleHostUserInterface.ReadLineResult.endedOnEnter;
			int num;
			this.HandleThrowOnReadAndPrompt();
			if (choices != null)
			{
				if (choices.Count != 0)
				{
					if (defaultChoice < -1 || defaultChoice >= choices.Count)
					{
						object[] objArray = new object[2];
						objArray[0] = "defaultChoice";
						objArray[1] = "choice";
						throw PSTraceSource.NewArgumentOutOfRangeException("defaultChoice", defaultChoice, "ConsoleHostUserInterfaceStrings", "InvalidDefaultChoiceErrorTemplate", objArray);
					}
					else
					{
						lock (this.instanceLock)
						{
							if (!string.IsNullOrEmpty(caption))
							{
								this.WriteLineToConsole();
								this.WriteToConsole(this.PromptColor, this.RawUI.BackgroundColor, this.WrapToCurrentWindowWidth(caption));
								this.WriteLineToConsole();
							}
							if (!string.IsNullOrEmpty(message))
							{
								this.WriteLineToConsole(this.WrapToCurrentWindowWidth(message));
							}
							int num1 = defaultChoice;
							string[,] strArrays = null;
							HostUIHelperMethods.BuildHotkeysAndPlainLabels(choices, out strArrays);
							Dictionary<int, bool> nums = new Dictionary<int, bool>();
							if (defaultChoice >= 0)
							{
								nums.Add(defaultChoice, true);
							}
							do
							{
							Label0:
								this.WriteChoicePrompt(strArrays, nums, false);
								string str = this.ReadLine(false, "", out readLineResult, true, true);
								if (readLineResult != ConsoleHostUserInterface.ReadLineResult.endedOnBreak)
								{
									if (str.Length != 0)
									{
										if (str.Trim() != "?")
										{
											num1 = HostUIHelperMethods.DetermineChoicePicked(str.Trim(), choices, strArrays);
										}
										else
										{
											this.ShowChoiceHelp(choices, strArrays);
											goto Label0;
										}
									}
									else
									{
										if (defaultChoice >= 0)
										{
											num1 = defaultChoice;
											break;
										}
										else
										{
											goto Label0;
										}
									}
								}
								else
								{
									string promptCanceledError = ConsoleHostUserInterfaceStrings.PromptCanceledError;
									PromptingException promptingException = new PromptingException(promptCanceledError, null, "PromptForChoiceCanceled", ErrorCategory.OperationStopped);
									throw promptingException;
								}
							}
							while (num1 < 0);
							num = num1;
						}
						return num;
					}
				}
				else
				{
					object[] objArray1 = new object[1];
					objArray1[0] = "choices";
					throw PSTraceSource.NewArgumentException("choices", "ConsoleHostUserInterfaceStrings", "EmptyChoicesErrorTemplate", objArray1);
				}
			}
			else
			{
				throw PSTraceSource.NewArgumentNullException("choices");
			}
		}
Пример #4
0
		public override Dictionary<string, PSObject> Prompt(string caption, string message, Collection<FieldDescription> descriptions)
		{
			Dictionary<string, PSObject> strs;
			this.HandleThrowOnReadAndPrompt();
			if (descriptions != null)
			{
				if (descriptions.Count >= 1)
				{
					lock (this.instanceLock)
					{
						Dictionary<string, PSObject> strs1 = new Dictionary<string, PSObject>();
						bool flag = false;
						if (!string.IsNullOrEmpty(caption))
						{
							this.WriteLineToConsole();
							this.WriteToConsole(this.PromptColor, this.RawUI.BackgroundColor, this.WrapToCurrentWindowWidth(caption));
							this.WriteLineToConsole();
						}
						if (!string.IsNullOrEmpty(message))
						{
							this.WriteLineToConsole(this.WrapToCurrentWindowWidth(message));
						}
						if (ConsoleHostUserInterface.AtLeastOneHelpMessageIsPresent(descriptions))
						{
							this.WriteLineToConsole(this.WrapToCurrentWindowWidth(ConsoleHostUserInterfaceStrings.PromptHelp));
						}
						int num = -1;
						foreach (FieldDescription description in descriptions)
						{
							num++;
							if (description != null)
							{
								PSObject pSObject = null;
								string name = description.Name;
								bool flag1 = true;
								if (!string.IsNullOrEmpty(description.ParameterAssemblyFullName))
								{
									Type fieldType = InternalHostUserInterface.GetFieldType(description);
									if (fieldType == null)
									{
										if (!InternalHostUserInterface.IsSecuritySensitiveType(description.ParameterTypeName))
										{
											fieldType = typeof(string);
										}
										else
										{
											string str = StringUtil.Format(ConsoleHostUserInterfaceStrings.PromptTypeLoadErrorTemplate, description.Name, description.ParameterTypeFullName);
											PromptingException promptingException = new PromptingException(str, null, "BadTypeName", ErrorCategory.InvalidType);
											throw promptingException;
										}
									}
									if (fieldType.GetInterface(typeof(IList).FullName) == null)
									{
										string str1 = StringUtil.Format(ConsoleHostUserInterfaceStrings.PromptFieldPromptInputSeparatorTemplate, name);
										object obj = null;
										bool flag2 = false;
										this.PromptForSingleItem(fieldType, str1, name, caption, message, description, flag1, false, out flag2, out flag, out obj);
										if (!flag)
										{
											pSObject = PSObject.AsPSObject(obj);
										}
									}
									else
									{
										ArrayList arrayLists = new ArrayList();
										Type elementType = typeof(object);
										if (fieldType.IsArray)
										{
											elementType = fieldType.GetElementType();
											int arrayRank = fieldType.GetArrayRank();
											if (arrayRank <= 0)
											{
												string str2 = StringUtil.Format(ConsoleHostUserInterfaceStrings.RankZeroArrayErrorTemplate, description.Name);
												object[] objArray = new object[1];
												objArray[0] = num;
												ArgumentException argumentException = PSTraceSource.NewArgumentException(string.Format(CultureInfo.InvariantCulture, "descriptions[{0}].AssemblyFullName", objArray));
												PromptingException promptingException1 = new PromptingException(str2, argumentException, "ZeroRankArray", ErrorCategory.InvalidOperation);
												throw promptingException1;
											}
										}
										StringBuilder stringBuilder = new StringBuilder(name);
										stringBuilder.Append("[");
										while (true)
										{
											object[] count = new object[1];
											count[0] = arrayLists.Count;
											stringBuilder.Append(string.Format(CultureInfo.InvariantCulture, "{0}]: ", count));
											bool flag3 = false;
											object obj1 = null;
											this.PromptForSingleItem(elementType, stringBuilder.ToString(), name, caption, message, description, flag1, true, out flag3, out flag, out obj1);
											if (flag || flag3)
											{
												break;
											}
											if (!flag)
											{
												arrayLists.Add(obj1);
												stringBuilder.Length = name.Length + 1;
											}
										}
										if (!flag)
										{
											object obj2 = null;
											if (!LanguagePrimitives.TryConvertTo(arrayLists, fieldType, out obj2))
											{
												pSObject = PSObject.AsPSObject(arrayLists);
											}
											else
											{
												pSObject = PSObject.AsPSObject(obj2);
											}
										}
									}
									if (!flag)
									{
										strs1.Add(description.Name, PSObject.AsPSObject(pSObject));
									}
									else
									{
										ConsoleHostUserInterface.tracer.WriteLine("Prompt canceled", new object[0]);
										this.WriteLineToConsole();
										strs1.Clear();
										break;
									}
								}
								else
								{
									object[] objArray1 = new object[1];
									objArray1[0] = num;
									string str3 = string.Format(CultureInfo.InvariantCulture, "descriptions[{0}].AssemblyFullName", objArray1);
									object[] objArray2 = new object[1];
									objArray2[0] = str3;
									throw PSTraceSource.NewArgumentException(str3, "ConsoleHostUserInterfaceStrings", "NullOrEmptyErrorTemplate", objArray2);
								}
							}
							else
							{
								object[] objArray3 = new object[1];
								object[] objArray4 = new object[1];
								objArray4[0] = num;
								objArray3[0] = string.Format(CultureInfo.InvariantCulture, "descriptions[{0}]", objArray4);
								throw PSTraceSource.NewArgumentException("descriptions", "ConsoleHostUserInterfaceStrings", "NullErrorTemplate", objArray3);
							}
						}
						strs = strs1;
					}
					return strs;
				}
				else
				{
					object[] objArray5 = new object[1];
					objArray5[0] = "descriptions";
					throw PSTraceSource.NewArgumentException("descriptions", "ConsoleHostUserInterfaceStrings", "PromptEmptyDescriptionsErrorTemplate", objArray5);
				}
			}
			else
			{
				throw PSTraceSource.NewArgumentNullException("descriptions");
			}
		}
        /// <summary>
        /// 
        /// See base class
        /// 
        /// </summary>
        /// <param name="caption"></param>
        /// <param name="message"></param>
        /// <param name="choices"></param>
        /// <param name="defaultChoice"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentNullException">
        /// 
        /// If <paramref name="choices"/> is null.
        /// 
        /// </exception>
        /// <exception cref="ArgumentException">
        /// 
        /// If <paramref name="choices"/>.Count is 0.
        /// 
        /// </exception>
        /// <exception cref="ArgumentOutOfRangeException">
        /// 
        /// If <paramref name="defaultChoice"/> is greater than
        ///     the length of <paramref name="choices"/>.
        /// 
        /// </exception>
        /// <exception cref="PromptingException">
        /// 
        ///  when prompt is canceled by, for example, Ctrl-c.
        /// 
        /// </exception>

        public override int PromptForChoice(string caption, string message, Collection<ChoiceDescription> choices, int defaultChoice)
        {
            HandleThrowOnReadAndPrompt();

            if (choices == null)
            {
                throw PSTraceSource.NewArgumentNullException("choices");
            }

            if (choices.Count == 0)
            {
                throw PSTraceSource.NewArgumentException("choices",
                    ConsoleHostUserInterfaceStrings.EmptyChoicesErrorTemplate, "choices");
            }

            if ((defaultChoice < -1) || (defaultChoice >= choices.Count))
            {
                throw PSTraceSource.NewArgumentOutOfRangeException("defaultChoice", defaultChoice,
                    ConsoleHostUserInterfaceStrings.InvalidDefaultChoiceErrorTemplate, "defaultChoice", "choice");
            }

            // we lock here so that multiple threads won't interleave the various reads and writes here.

            lock (_instanceLock)
            {
                if (!string.IsNullOrEmpty(caption))
                {
                    // Should be a skin lookup

                    WriteLineToConsole();
                    WriteToConsole(PromptColor, RawUI.BackgroundColor, WrapToCurrentWindowWidth(caption));
                    WriteLineToConsole();
                }

                if (!string.IsNullOrEmpty(message))
                {
                    WriteLineToConsole(WrapToCurrentWindowWidth(message));
                }

                int result = defaultChoice;

                string[,] hotkeysAndPlainLabels = null;
                HostUIHelperMethods.BuildHotkeysAndPlainLabels(choices, out hotkeysAndPlainLabels);

                Dictionary<int, bool> defaultChoiceKeys = new Dictionary<int, bool>();
                // add the default choice key only if it is valid. -1 is used to specify
                // no default.
                if (defaultChoice >= 0)
                {
                    defaultChoiceKeys.Add(defaultChoice, true);
                }

                do
                {
                    WriteChoicePrompt(hotkeysAndPlainLabels, defaultChoiceKeys, false);

                    ReadLineResult rlResult;
                    string response = ReadLine(false, "", out rlResult, true, true);

                    if (rlResult == ReadLineResult.endedOnBreak)
                    {
                        string msg = ConsoleHostUserInterfaceStrings.PromptCanceledError;
                        PromptingException e = new PromptingException(
                            msg, null, "PromptForChoiceCanceled", ErrorCategory.OperationStopped);
                        throw e;
                    }

                    if (response.Length == 0)
                    {
                        // they just hit enter.  

                        if (defaultChoice >= 0)
                        {
                            // if there's a default, pick that one.

                            result = defaultChoice;
                            break;
                        }

                        continue;
                    }

                    // decide which choice they made.

                    if (response.Trim() == "?")
                    {
                        // show the help

                        ShowChoiceHelp(choices, hotkeysAndPlainLabels);
                        continue;
                    }

                    result = HostUIHelperMethods.DetermineChoicePicked(response.Trim(), choices, hotkeysAndPlainLabels);

                    if (result >= 0)
                    {
                        break;
                    }

                    // their input matched none of the choices, so prompt again
                }
                while (true);

                return result;
            }
        }
        /// <summary>
        /// Presents a dialog allowing the user to choose options from a set of options.
        /// </summary>
        /// <param name="caption">
        /// Caption to precede or title the prompt.  E.g. "Parameters for get-foo (instance 1 of 2)"
        /// </param>
        /// <param name="message">
        /// A message that describes what the choice is for.
        /// </param>
        /// <param name="choices">
        /// An Collection of ChoiceDescription objects that describe each choice.
        /// </param>
        /// <param name="defaultChoices">
        /// The index of the labels in the choices collection element to be presented to the user as 
        /// the default choice(s). 
        /// </param>
        /// <returns>
        /// The indices of the choice elements that corresponds to the options selected.
        /// </returns>
        /// <seealso cref="System.Management.Automation.Host.PSHostUserInterface.PromptForChoice"/>
        public Collection<int> PromptForChoice(string caption,
            string message,
            Collection<ChoiceDescription> choices,
            IEnumerable<int> defaultChoices)
        {
            HandleThrowOnReadAndPrompt();

            if (choices == null)
            {
                throw PSTraceSource.NewArgumentNullException("choices");
            }

            if (choices.Count == 0)
            {
                throw PSTraceSource.NewArgumentException("choices",
                    ConsoleHostUserInterfaceStrings.EmptyChoicesErrorTemplate, "choices");
            }

            Dictionary<int, bool> defaultChoiceKeys = new Dictionary<int, bool>();

            if (null != defaultChoices)
            {
                foreach (int defaultChoice in defaultChoices)
                {
                    if ((defaultChoice < 0) || (defaultChoice >= choices.Count))
                    {
                        throw PSTraceSource.NewArgumentOutOfRangeException("defaultChoice", defaultChoice,
                            ConsoleHostUserInterfaceStrings.InvalidDefaultChoiceForMultipleSelection,
                            "defaultChoice",
                            "choices",
                            defaultChoice);
                    }

                    if (!defaultChoiceKeys.ContainsKey(defaultChoice))
                    {
                        defaultChoiceKeys.Add(defaultChoice, true);
                    }
                }
            }

            Collection<int> result = new Collection<int>();
            // we lock here so that multiple threads won't interleave the various reads and writes here.
            lock (_instanceLock)
            {
                // write caption on the console, if present.
                if (!string.IsNullOrEmpty(caption))
                {
                    // Should be a skin lookup
                    WriteLineToConsole();
                    WriteToConsole(PromptColor, RawUI.BackgroundColor, WrapToCurrentWindowWidth(caption));
                    WriteLineToConsole();
                }
                // write message
                if (!string.IsNullOrEmpty(message))
                {
                    WriteLineToConsole(WrapToCurrentWindowWidth(message));
                }

                string[,] hotkeysAndPlainLabels = null;
                HostUIHelperMethods.BuildHotkeysAndPlainLabels(choices, out hotkeysAndPlainLabels);

                WriteChoicePrompt(hotkeysAndPlainLabels, defaultChoiceKeys, true);
                if (defaultChoiceKeys.Count > 0)
                {
                    WriteLineToConsole();
                }

                // used to display ChoiceMessage like Choice[0],Choice[1] etc
                int choicesSelected = 0;
                do
                {
                    // write the current prompt
                    string choiceMsg = StringUtil.Format(ConsoleHostUserInterfaceStrings.ChoiceMessage, choicesSelected);
                    WriteToConsole(PromptColor, RawUI.BackgroundColor, WrapToCurrentWindowWidth(choiceMsg));

                    ReadLineResult rlResult;
                    string response = ReadLine(false, "", out rlResult, true, true);

                    if (rlResult == ReadLineResult.endedOnBreak)
                    {
                        string msg = ConsoleHostUserInterfaceStrings.PromptCanceledError;
                        PromptingException e = new PromptingException(
                            msg, null, "PromptForChoiceCanceled", ErrorCategory.OperationStopped);
                        throw e;
                    }

                    // they just hit enter
                    if (response.Length == 0)
                    {
                        // this may happen when
                        // 1. user wants to go with the defaults
                        // 2. user selected some choices and wanted those
                        // choices to be picked.

                        // user did not pick up any choices..choose the default
                        if ((result.Count == 0) && (defaultChoiceKeys.Keys.Count >= 0))
                        {
                            // if there's a default, pick that one.
                            foreach (int defaultChoice in defaultChoiceKeys.Keys)
                            {
                                result.Add(defaultChoice);
                            }
                        }
                        // allow for no choice selection.
                        break;
                    }

                    // decide which choice they made.
                    if (response.Trim() == "?")
                    {
                        // show the help
                        ShowChoiceHelp(choices, hotkeysAndPlainLabels);
                        continue;
                    }

                    int choicePicked = HostUIHelperMethods.DetermineChoicePicked(response.Trim(), choices, hotkeysAndPlainLabels);

                    if (choicePicked >= 0)
                    {
                        result.Add(choicePicked);
                        choicesSelected++;
                    }
                    // prompt for multiple choices
                }
                while (true);

                return result;
            }
        }