Powershell: Read-Host to select an Array Index

1.4k views Asked by At

This is how I modify my Powershell array:

ForEach ($userID in $usersList) {
    $allUsers += [pscustomobject]@{ID=$usersCounterTable;UserID=$userID;Name=$userInfo.DisplayName;Ext=$userInfo.ipPhone;Cellphone=$userInfo.mobile;Enabled=$isEnabled;VDI=$computerType;Title=$userTitle;}
    $usersCounter += 1
    $usersCounterTable = "[$usersCounter]"
}

Later in the code, the table is displayed and I want the user to be able to type a number to open the value, the number actually being the array index/offset (minus 1). I cannot find out how to do this.

$userID is actually the user's selection, because they can also type another employee's code to search, or search for his name for instance. I want the user to be able to select the array index number.

if (($userID.length -gt 0) -and ($userID.length -lt 5)) {
    $indexNumber = ($userID - 1)
    [????]  $userFinalChoice = $allUsers[$userID].Name  # NOT VALID
}

Above code works, if the user enter a number between 1 and 9999... And then I would like to do this: $allUsers[$userID] ($userID being the number the user selected with Read-Host). Only, $allUsers[$userID].Name is not valid, but $allUsers[1].Name is. If I can figure this out, I'll be able to fix the rest of it and search for the return value.

Also need to make sure user doesn't input an index that is out of bounds of $usersList (Using $ErrorActionPreference = "SilentlyContinue" would probably work as it just reject the search reject but it's not that clean.)

From what I understand, I'm actually looking for the reverse of $usersList.IndexOf(‘David’), I want to provide the index and get returned the name.

Much appreciated - Powershell beginner.

1

There are 1 answers

0
Theo On BEST ANSWER

The first code block you show us is really confusing, since you seem to grab user details from just... somewhere, so there is no telling if this info indeed belongs to the same user or not.

Also, I don't really think it is a good idea to use a formatted table as selection menu, especialy if the list gets large. Maybe you should think of building a form with a listbox or use the Out-GridView for this as Lee_Dailey suggested.

Anyway, if you want it as console menu, first make sure the ID number (really the index to select) starts with 1

$usersCounter = 1
# collect an array of PsCustomObjects in variable $allUsers
$allUsers = foreach ($userID in $usersList) {
    # don't use $allUsers += , simply output the object
    [PsCustomObject]@{
        ID        = "[$usersCounter]"
        UserID    = $userID
        Name      = $userInfo.DisplayName
        Ext       = $userInfo.ipPhone
        Cellphone = $userInfo.mobile
        Enabled   = $isEnabled
        VDI       = $computerType
        Title     = $userTitle
    }
    $usersCounter++   # increment the counter
}

Next, show this as table so folks can select one of the users by typing the number displayed in the 'ID' column. Do this in a loop, so when someone types anything else than a valid number, the menu is displayed again.

# start an endless loop
while ($true) {
    Clear-Host
    $allUsers | Format-Table -AutoSize
    $userID = Read-Host "Enter the [ID] number to select a user. Type 0 or Q to quit"
    if ($userID -eq '0' -or $userID -eq 'Q') { break }  # exit from the loop, user quits

    # test if the input is numeric and is in range
    $badInput = $true
    if ($userID -notmatch '\D') {    # if the input does not contain an non-digit
        $index = [int]$userID - 1
        if ($index -ge 0 -and $index -lt $allUsers.Count) {
            $badInput = $false
            # everything OK, you now have the index to do something with the selected user
            # for demo, just write confirmation to the console and exit the loop
            Clear-Host
            Write-Host "You have selected $($allUsers[$index].Name)" -ForegroundColor Green
            break
        }
    }
    # if you received bad input, show a message, wait a couple 
    # of seconds so the message can be read and start over
    if ($badInput) {
        Write-Host "Bad input received. Please type only a valid number from the [ID] column." -ForegroundColor Red
        Start-Sleep -Seconds 4
    }
}