2

I am writing a script to deploy VM hosts and I want to run a Get command to show them available options and then use their input with autocomplete from previous GET command. I do this because I want to avoid any typos that can be made during manual input.

I have tried using Select-string but I think it saves to .txt file and I don't want this to be saved in a txt file. I would rather have it saved in variable.

Get-VMHost | Select-Object -Property Name | Format-Table -Property Name
$VMHost = Read-Host -Prompt 'Please select the host for your VM

I expect the user to be able to autocomplete string with output from previously executed GET command. Please help if you can

Theo
  • 57,719
  • 8
  • 24
  • 41

2 Answers2

1

Here is a New-ChoicePrompt function I use for similar purposes.

function New-ChoicePrompt {  [cmdletBinding()]
  param( 
      [parameter(mandatory=$true)]$Choices, 
      $Property, 
      $ReadProperty, 
      $ExprLabel,
      [switch]$AllowManualInput, 
      [Scriptblock]$ReadPropertyExpr, 
      $ManualInputLabel = "Type my own"
  )
  if ( $choices[0] -isnot [string] -and !$property ) {"Please include New-ChoicePrompt -Property unless -Choices is an array of strings."; break}
  if ( $choices[0] -is [string] -and ($property -or $ReadProperty) ) {"When New-ChoicePrompt -Choices is an array of strings, please omit -Property and -ReadProperty."; break}
  #if ( $choices[0] -isnot [string] -and $allowManualInput ) {"When New-ChoicePrompt -Choices is a PSobject, please omit -AllowManualInput"; break}
  $x = 0; $script:options = @()
  $script:propty = $property
  $script:choices = $choices
  $manualInputLabel = "<" + $manualInputLabel + ">"
  foreach ($item in $choices) { $value = $null
    $x += 1
    if ($property) { $value = $item | select -expand $property } `
    else {$value = $item}
    if ($readProperty) {
      $readVal = $item | select -expand $readProperty
      $row = new-object -type psObject -property @{Press = $x; 'to select' = $value; $readproperty = $readVal}
    } ` #close if readProperty
    elseif ($readPropertyExpr) `
    {
      $readVal = & $ReadPropertyExpr
      $row = new-object -type psObject -property @{Press = $x; 'to select' = $value; $ExprLabel = $readVal}
    }` #close if readPropertyExpr
    else { $row = new-object -type psObject -property @{'to select' = $value; Press = $x} }
    $script:options += $row
  } #close foreach
  if ($AllowManualInput) {
    $row = new-object -type psObject -property @{'to select' = $manualInputLabel; Press = ($x + 1) }
    $script:options += $row
  } #close if allowManualInput
  if ($ReadProperty) { $script:options | Select Press, "to select", $readproperty | ft -auto }
  elseif ($ReadPropertyExpr) { $script:options | Select Press, "to select", $ExprLabel | ft -auto }
  else { $script:options | Select Press, "to select" | ft -auto }
} #end function new-choicePrompt

Here is a usage example.

  $vmhosts = Get-VMHost | sort Name
  if ($vmhosts.count -gt 1) {
    do {
      new-choicePrompt -choices $vmhosts -property name
      $in = read-host -prompt 'Please select a target host'
      $range = $options | select -expand press
    } #close do
    until ($range -contains $in)
    $selection = $options | where {$_.press -eq $in} | select -expand 'To select'
    $choice = $choices | where {$_.@($propty) -eq $selection} 
    $vmHost = $choice
  } else {$vmhost = $vmhosts} #close if multiple hosts
  "Target host: " + $vmhost.name
noam
  • 1,914
  • 2
  • 20
  • 26
0

If it was a function parameter, you could limit the values with [ValidateSet] like from here: https://www.mssqltips.com/sqlservertip/4205/powershell-parameters-part-ii--validateset-and-validatepattern/ It ends up supporting tab completion as well. If you set it to mandatory, it will prompt for it as well, if it's not given.

Function Pass-Set {
    Param(
        [ValidateSet("oro","plata")][string]$specificstring
    )
    Process
    {
        Write-Host "It must be one of two words; in this case $specificstring."
    }
}

pass-set -specificstring oro
It must be one of two words; in this case oro.

pass-set -specificstring plata
It must be one of two words; in this case plata.

pass-set -specificstring plata2
Pass-Set : Cannot validate argument on parameter 'specificstring'. The argument "plata2" does not belong to the set "oro,plata" specified by the
ValidateSet attribute. Supply an argument that is in the set and then try the command again.
At line:1 char:26
+ pass-set -specificstring plata2
+                          ~~~~~~
    + CategoryInfo          : InvalidData: (:) [Pass-Set], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationError,Pass-Set
js2010
  • 23,033
  • 6
  • 64
  • 66