Search code examples
arrayspowershellindexingoffsetread-host

Powershell: Read-Host to select an Array Index


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.


Solution

  • 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
        }
    }