5

I have a section of PowerShell code that reads a list of items from Azure, and formats them into a table for the user to choose from:

if ($SubscriptionArray.Count -eq 1) {
    $SelectedSub = 1
}
# Get SubscriptionID if one isn't provided
while ($SelectedSub -gt $SubscriptionArray.Count -or $SelectedSub -lt 1) {
    Write-host "Please select a subscription from the list below"
    $SubscriptionArray | Select-Object "#", Id, Name | Format-Table
    try {
        $SelectedSub = Read-Host "Please enter a selection from 1 to $($SubscriptionArray.count)"
    }
    catch {
        Write-Warning -Message 'Invalid option, please try again.'
    }
}

When executed in the main area of the script, this outputs the expected result:

AzureTableOutput

I want to use this logic multiple times, and therefore moved it into a method:

function Get-IndexNumberFromArray(
    [Parameter(Mandatory = $True)]
    [array]$selectArray,

    [Parameter(Mandatory = $True)]
    [string]$message
) {
    [int]$SelectedIndex = 0
    # use the current subscription if there is only one subscription available
    if ($selectArray.Count -eq 1) {
        $SelectedIndex = 1
    }

    # Get SubscriptionID if one isn't provided
    while ($SelectedIndex -gt $selectArray.Count -or $SelectedIndex -lt 1) {
        Write-Host "$message"

        $selectArray | Select-Object "#", Id, Name | Format-Table

        try {
            $SelectedIndex = Read-Host "Please enter a selection from 1 to $($selectArray.count)"
        }
        catch {
            Write-Warning -Message 'Invalid option, please try again.'
        }
    }

    return $SelectedIndex
}

Everything in this method works great, except now my table is no longer outputting to the window. Instead, the user just get a prompt to pick a number from 1 to x with no context for what each number represents.

Why is the table working in the main area of the script, but not working in a function?

Micha Wiedenmann
  • 19,979
  • 21
  • 92
  • 137
Bic
  • 3,141
  • 18
  • 29

1 Answers1

11

Format-Table actually doesn't print a table, it outputs objects that are then printed as the table. So if you're using a function, then the Format-Table output gets part of the return value of your function.

You can add Out-Host to the pipeline to force Format-Table's result to end up on the host, i.e. the console:

$selectArray | Select-Object "#", Id, Name | Format-Table | Out-Host
Joey
  • 344,408
  • 85
  • 689
  • 683
  • The answer is so simple... Thanks! I figured that Out-Host was the default. – Bic Mar 12 '18 at 15:10
  • 1
    It's the default cmdlet that is effectively added to every pipeline you write interactively. But not in scripts (or functions, which are effectively the same). – Joey Mar 12 '18 at 15:12
  • 1
    Frustratingly, this now (PS 7.1) outputs `Microsoft.PowerShell.Commands.Internal.Format.FormatEntryData`. `$item | Format-Table | Out-String | Write-Host` as described by https://stackoverflow.com/questions/36585500/how-to-display-formatted-output-with-write-host#comment97535863_36585818 worked for me. – timelmer Feb 19 '21 at 22:53