Powershell and [System.Management.Automation.Host.ChoiceDescription[]]

Soldato
Joined
8 Mar 2005
Posts
3,860
Location
London, UK
I've knock up some code, which creates an array and then presents objects within that array as a choice; however it presents a column name instead of a numbered index:

current output:
Code:
Which session do you wish to kill?
[] Session A  [] Session B  [?] Help (default is "Session A"):
target output:
Code:
Which session do you wish to kill?
[1] Session A  [2] Session B  [?] Help (default is "Session A"):
I'm almost there but not quite. Here is the code which runs and executes successfully but when choosing anything other than the default, the entire session name needs to be typed out.
Code:
if($a.count -gt 1){
        $title = "Session Selection"
        $message = "Which session do you wish to kill?"
        # Build the choices menu
        $choices = @()
        #$choicesarray = @()
        #$i = 0
        For($index = 0; $index -lt $a.Count; $index++){
            $choices += New-Object System.Management.Automation.Host.ChoiceDescription ($a[$index]).DesktopGroupName, ($a[$index]).SessionState
            #$i++
        }
        $options = [System.Management.Automation.Host.ChoiceDescription[]]($choices)
        $result = $host.ui.PromptForChoice($title, $message, $options, 0)
        $a = $a[$result]
    }
$i is where I've tried to play with creating an index but without success when trying to plug it into System.Management.Automation.Host.ChoiceDescription

Any pointers, much appreciated.
TIA!
 
Not sure if any help but tried to re-create using just the top three services on a box:
Code:
$Services = Get-Service | Select -First 3

$Choices = @()
ForEach ($Service In $Services)
{
    $Choices += New-Object System.Management.Automation.Host.ChoiceDescription $Service.Name, $Service.Status
}

$options = [System.Management.Automation.Host.ChoiceDescription[]]($choices)

$title   = "Session Selection"
$message = "Which session do you wish to kill?"
$result  = $host.ui.PromptForChoice($title, $message, $options, 0)

Write-Host "Kill Service $($options[$result].Label)"

Above stops short of killing the service ;)

Not used these ui gubbins before so some of the above may not be necessary.
Anyway, $result just pulls back the index of the choice you make.

Choices and options have two fields (btw, don't think both are needed - they apeear to be the same?), label and helpmessage so maybe you need to reference the label like above and pass that through to whatever will kill your session?
 
So, the output is exactly the same when you run this on console (or in ISE for that matter); we've produced the same output in slightly different ways :)
Your code:
Code:
Session Selection
Which session do you wish to kill?
[] AdobeARMservice  [] AeXAgentSrvHost  [] AeXNSClient  [?] Help (default is "AdobeARMservice"):
I'm after;
Code:
Session Selection
Which session do you wish to kill?
[1] AdobeARMservice  [2] AeXAgentSrvHost  [3] AeXNSClient  [?] Help (default is "AdobeARMservice"):
The user then inputs the number index corresponding to the service/session instead of the actual service/session name.
Make sense?

e:

Not to confuse matters, but I was looking at this as another example but even in this code I cannot fathom how the first letter of each colour is used as the index!
Code:
$red = New-Object System.Management.Automation.Host.ChoiceDescription '&Red', 'Favorite color: Red'
$blue = New-Object System.Management.Automation.Host.ChoiceDescription '&Blue', 'Favorite color: Blue'
$yellow = New-Object System.Management.Automation.Host.ChoiceDescription '&Yellow', 'Favorite color: Yellow'
$options = [System.Management.Automation.Host.ChoiceDescription[]]($red, $blue, $yellow)
$title = 'Favorite color'
$message = 'What is your favorite color?'
$result = $host.ui.PromptForChoice($title, $message, $options, 0)
when run on console:
Code:
Favorite color
What is your favorite color?
[R] Red  [B] Blue  [Y] Yellow  [?] Help (default is "R"):

To be clear; I'm still after a numbered index as opposed to the first letter of the session name.
 
Last edited:
According to the documentation, whatever you prefix with & will become the shortcut for selecting.

So with your original code you just needed to add your index into the label string:

Code:
$choices += New-Object System.Management.Automation.Host.ChoiceDescription ("&$($index+1) $($a[$index]).DesktopGroupName)", "$($a[$index]).SessionState)")

(using $index+1 in the label if you want the option for the person to input to start starts at 1 rather than 0)

You'll end up with the number twice, but I don't think there is anyway around that.

Code:
[1] 1 This is a test  [?] Help (default is "1"): 1
 
Hmm ok thanks. I'll need to rework it slightly as ("&$($index+1) $($a[$index]).DesktopGroupName)", "$($a[$index]).SessionState)") outputs all columns in the array instead of just DesktopGroupName.
 
Looking again I think there are an extra couple of ) which shouldn't be there, try:

Code:
$choices += New-Object System.Management.Automation.Host.ChoiceDescription ("&$($index+1) $($a[$index].DesktopGroupName)", "$($a[$index].SessionState)")
 
So, the output is exactly the same when you run this on console (or in ISE for that matter); we've produced the same output in slightly different ways :)

Aha! Sorry, just ran through ISE and on my machine actually popped up buttons to press rather than the command line inputs. Seems you've sussed it with sticking the index+1 at the start of the label.

Edit:
Just to say, you can do a fairly basic input yourself quite easily if you don't like the promptforchoice thing.

Code:
Function Select-WorkFolderGroup
{
    Param
    (
        $WorkFolderGroups
    )

    Write-Host "`nWorkFolder Groups"
    Write-Host "-----------------"
   
    For ($i=1; $i -Le $WorkFolderGroups.Count; $i++)
    {
        Write-Host "$i. $($WorkFolderGroups[$i-1].Name): $($WorkFolderGroups[$i-1].Count)"
    }  
    Write-Host "`nUse Ctrl+C to Exit`n"

    $Input = Read-Host "Select WorkFolder Group to add user to"

    Write-Host "Group Selected: $($WorkFolderGroups[$Input-1].Name)"

    # Return
    $WorkFolderGroups[$Input-1].Name
}

There's zero validation going on in the above but fairly easy to add in ;)
 
Last edited:
Back
Top Bottom