1

Why is the hash table output a single string not a array?


$ServicesList = @{
    "Exhange Online"               = "Connect-ExchangeOnline"
    "Security & Compliance Center" = "Connect-IPPSSession"
    "Azure Active Directory"       = "Connect-AzureAD"
    "Microsoft Online"             = "Connect-MsolService"
    "SharePoint Online"            = "Connect-SPOService -Url $url"
    "Microsoft Teams"              = "Connect-MicrosoftTeams"
    "Microsoft Graph"              = "Connect-Graph"
    "Azure Account"                = "Connect-AzAccount"
}

$ServicesListKeys = $ServicesList.Keys

function Menu {
    $menu = @{}
    for ($i = 1; $i -le $ServicesListKeys.count; $i++) {
        Write-Host "$i. $($ServicesListKeys[$i-1])" 
        $menu.Add($i, ($ServicesListKeys[$i - 1]))
    }
    [int]$ans = Read-Host 'Enter selection'
    $selection = $menu.Item($ans) ; $ServicesList[$selection]
}

Menu

Output:

  1. Azure Active Directory Microsoft Graph Microsoft Online Azure Account Security & Compliance Center Exhange Online Microsoft Teams SharePoint Online

when it workers with a normal array

$array = "Red", "green", "Blue"

Output:

  1. Red
  2. green
  3. Blue
1
  • 2
    $ServicesListKeys is not indexable, so PowerShell returns the object itself for $ServicesListKeys[0], and `````$null``` for all other indices. Compare to (1`)[0] (returns 1) vs (1)[1] (returns $null). You can coerce it into an array with $ServicesListKeys =@( $ServicesList.Keys ) and then your remaining code will work fine... Commented Sep 11, 2022 at 16:55

1 Answer 1

2

Hashtable only supports Item[Object]:

Gets or sets the value associated with the specified key.

Whereas OrderedDictionary supports both, Item[Object] and Item[Int32], the latter being:

Gets or sets the value at the specified index.

In this case you could simply change your hashtable for an ordered dictionary, not only because it supports getting values by index but also because the key / value pairs will always retain the same order. By using a hashtable, the items on your Menu not always have the same order.

Here is a simplified working version of your code:

$ServicesList = [ordered]@{
    "Exhange Online"               = "Connect-ExchangeOnline"
    "Security & Compliance Center" = "Connect-IPPSSession"
    "Azure Active Directory"       = "Connect-AzureAD"
    "Microsoft Online"             = "Connect-MsolService"
    "SharePoint Online"            = "Connect-SPOService -Url $url"
    "Microsoft Teams"              = "Connect-MicrosoftTeams"
    "Microsoft Graph"              = "Connect-Graph"
    "Azure Account"                = "Connect-AzAccount"
}

function Menu {
    param($Dictionary)

    $i = 1; $ServicesList.PSBase.Keys | ForEach-Object {
        Write-Host "$(($i++)). $_"
    }

    [int] $ans = Read-Host 'Enter selection'

    if($value = $Dictionary[$ans - 1]) {
        return $value
    }
    Write-Warning "Invalid selection!"
}

Menu -Dictionary $ServicesList
Sign up to request clarification or add additional context in comments.

2 Comments

Your code returns: 1.Exhange Online Security & Compliance Center Azure Active Directory Microsoft Online SharePoint Online Microsoft Teams Microsoft Graph Azure Account 2. 3. 4. 5. 6. 7. 8. Enter selection:
@ScratchIV that was my bad, it behaves different in pwsh 7 and pwsh 5. in pwsh 7 something like $ServicesList.Keys[0] would work fine. Please try again with the updated version

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.