Powershell Dynamic Menu from Object Array

Ya know what grinds my gears?  Getting a CSV of employees without a unique key column – no samaccountname, UPN, email, DistinguishedName, SID – nothing.  Sometimes you’ll even get supplied with a column of <firstname><space><lastname> using 3rd party information that doesn’t mesh with AD info either.  Nice.

The function below can be used with an interactive script so you can select the proper object to report on/target/add to another array.  Without any editing the AD objects will display their DN when enumerated from the hash.  Input validation is also present and will only accept the range of numbers determined within the function or cancel and return null.

function Show-DynamicMenu
{
  [CmdletBinding()]
  Param
  (
    [Parameter(Mandatory=$true,Position=0)]
    [ValidateNotNullOrEmpty()]
    $objArr
  )
 
  $count = 1
  $total = ($objArr | measure).count
 
  if($total -eq 1){return $objArr} #I knew you would do it; thank me later
  
  $menuHash = @{}
  $objArr | % {$menuHash[$count] = $_;$count++}
  
  $pad = $total.ToString().Length
  1..$total | % {Write-Host $($_.ToString().PadLeft($pad) + ")  " + $menuHash[$_])} #display menu selections
  do
  {
    do
    {
      $selection = $null
      $selection = Read-Host "Select object [c to cancel]"
      if($selection -eq 'c'){return $null}
    }
    while($selection -notmatch '^\d+$') #validate numeric only entry
  }
  while([int]$selection -lt 1 -or [int]$selection -gt $total) #validate numeric entry is in range
 
  $menuHash[[int]$selection]
}

#simple example
$obj = 1..100 | % {New-Object -TypeName psobject -Property @{name="user${_}";id=Get-Random -min 1 -max 400}}

Show-DynamicMenu $obj