suitedupgeek
suitedupgeek

Reputation: 885

PowerShell - Passing hashtables to a function

I'm in the process of writing a CLI for a thing I'm working on, and at various points in the process I want to ask the user for input. Each time I ask the user for input, the questions/answers are likely to be different so I started out with something like:

$choices = [Management.Automation.Host.ChoiceDescription[]] @(
    New-Object Management.Automation.Host.ChoiceDescription("&Yes","Option Description for Yes")
    New-Object Management.Automation.Host.ChoiceDescription("&No","Option Description for No.")
)
$choice = $Host.UI.PromptForChoice("Question Title","Question Text",$choices,1)

This works pretty well, but it's a bit clunky when it comes to re-use especially if the number of choices expands.

I want to wrap it in a function that I can call easier - like:

$options = @{
            Yes = "Option Description for Yes" 
            No = "Option Description for No"
        }
askQuestion -title "Question Title" -question "Question Text" -options $options

So far so good. The bit I'm struggling with is accessing the properties of $options:

function askQuestion {
    param (
        [hashtable]$options,
        [string]$title,
        [string]$question
    )
    Write-Host $title -ForegroundColor Cyan
    Write-Host $question -ForegroundColor Cyan

    foreach($option in $options)
    {
        # Do stuff HERE
    }
}

If I just access $option directly in the foreach, it prints out a table like:

Name                           Value
----                           -----
No                             Option Description for No
Yes                            Option Description for Yes

If I try accessing $option.Name or .Value it doesn't seem to do anything at all.

Can someone point out where I'm going wrong with this please?

Upvotes: 0

Views: 213

Answers (2)

suitedupgeek
suitedupgeek

Reputation: 885

For anyone interested, this is what this finished up looking like:

function askQuestion {
    param (
        [hashtable]$options,
        [string]$title,
        [string]$question
    )

    $choices = [Management.Automation.Host.ChoiceDescription[]] @(
        foreach ($option in $options.GetEnumerator()) {
            $selection = $option.key
            $description = $option.value
            New-Object Management.Automation.Host.ChoiceDescription("&$selection",$description)
         }
    )
    $choice = $Host.UI.PromptForChoice($title,$question,$choices,1)
    return
}

And it can be called with something like this, where $options is very flexible.

$options = @{
    Yes = "Yes Description" 
    No = "No Description"
    Maybe = "Maybe Description"
}

askQuestion -title "Question Title" -question "Question Text" -options $options

Upvotes: 1

AdminOfThings
AdminOfThings

Reputation: 25001

I think you can use the GetNumerator() method to iterate through the hash table entries. Then create a custom message using the format operator -f. $i here is just something to track a number for each line in the output. This should be fairly dynamic provided your values/descriptions are consistently worded so there are no grammatical/comprehension issues.

$i = 1
foreach ($option in $options.GetEnumerator()) {
    "{2}. Enter {0} for {1}" -f $option.key,$option.value,$i++
}

Upvotes: 2

Related Questions