- Create a certificate-signed RDP shortcut via Group Policy - Fri, Aug 9 2019
- Monitor web server uptime with a PowerShell script - Tue, Aug 6 2019
- How to build a PowerShell inventory script for Windows Servers - Fri, Aug 2 2019
In order to write code that’s reusable, it's important not to hardcode values that may change at some future point. The best practice is to separate the input values from the processing and the output. In PowerShell, there are many ways to make this happen including using command-line parameters, building fancy GUIs, using input boxes, and so on. Your exact situation will dictate which method you choose.
Constructing an interactive menu that allows the user to select between different options is a great way to build scripts for less PowerShell-savvy people, or it can simply be used as a kind of input gateway to a lot of the functionality that you’ve already built in PowerShell.
Let’s go over how to build a rudimentary interactive menu in the PowerShell console.
This menu consists of two main components: a function that displays the menu, and a switch statement that takes the input and directs the code which way to go, depending on the selection. First, we’ll build the menu function. I’ll call this Show-Menu.
function Show-Menu { param ( [string]$Title = 'My Menu' ) Clear-Host Write-Host "================ $Title ================" Write-Host "1: Press '1' for this option." Write-Host "2: Press '2' for this option." Write-Host "3: Press '3' for this option." Write-Host "Q: Press 'Q' to quit." }
This is a simple function that first clears the console and then writes a few lines to it. When ran with the title parameter set to 'My Menu', it will look like this:
Show-Menu –Title 'My Menu'
This is great, but as you can see, it dropped me back to the console again. I had no way to actually provide input to the menu. We need a way to make it pause after the menu is displayed to allow me to send it a keystroke. To do this, I can put a Read-Host immediately afterward to ask me for input.
Show-Menu –Title 'My Menu' $selection = Read-Host "Please make a selection"
I can now provide some kind of input, but it's still not functional. I have no way to do anything with the input once PowerShell receives it. I need a way to achieve something, depending on the input. A great construct to use here is the switch statement.
Show-Menu –Title 'My Menu' $selection = Read-Host "Please make a selection" switch ($selection) { '1' { 'You chose option #1' } '2' { 'You chose option #2' } '3' { 'You chose option #3' } 'q' { return } }
I now have the opportunity to do something with the input I receive from Read-Host.
Awesome! This works great. but maybe I want to do something and then keep the menu up until I say otherwise (by hitting the 'Q' key). I need the menu to come up again and again after I select an option. To do this, I can use a do/until loop. This lets me do something based on the menu selection, and then immediately render the menu again until 'Q' has been selected.
Subscribe to 4sysops newsletter!
do { Show-Menu $selection = Read-Host "Please make a selection" switch ($selection) { '1' { 'You chose option #1' } '2' { 'You chose option #2' } '3' { 'You chose option #3' } } pause } until ($selection -eq 'q')
At this point, when this script is run, it will display the menu and prompt for a selection. Once the selection is made, the switch statement will decide what to do. It will then pause, as a demonstration, to show the output of the selection. Then, if only 'Q' is chosen, it will break out of the loop and return control to the console.
What a great und useful article!
Thank you Adam!
User experience starts with a menu. I will stop showing codes and will put focus on showing menus for each task. Thank you for he useful post.
Hi Adam,
I managed to create an interactive menu, how would I get it to run some get script i have already develop example
So I have some individual script that can get a AAD user etc and i want to use an interactive menu to give the user the option
example below
Write-Host “================ $Title ================”
Write-Host “1: Press ‘1’ Get AAD Users.”
Write-Host “2: Press ‘2’ Get AAD Devices.”
Write-Host “3: Press ‘3’ Get AAD Devices”
Write-Host “Q: Press ‘Q’ to quit.”
}
do
{
Show-Menu
$input = Read-Host “Please select a task by number Or Q to Quit”
switch ($input)
{
‘1’ {
cls
‘You chose option #1’
} ‘2’ {
cls
‘You chose option #2’
} ‘3’ {
cls
‘You chose option #3’
} ‘q’ {
return
}
}
pause
}
until ($input -eq ‘q’)
im getting the menu option but i need to now pass the function to a menu parameter the script at the end of each action to execute my script or do i add a loop.
any direction would be helpful
i don’t know what is the problem, but i stuck here:
Complete script for your reference
The script looks good and I'd like to use it but when I modify it I never see the results onscreen.
What do I need to change to see the results?
Thank you.
Hi Michael,
The script above provides a basic framework for menu and IO system.
You could fill in the blocks, extend it or further improve it.
If you could provide me with details of modifications I would be glad to help you identify the break in the flow.
Great article, exactly was I was looking for, simple and very clear.
Is there a way to add some fun by adding an “else” for if the user selects something not on the list (say they randomly type “whatever…” and press enter, where it’ll recognize that it’s not an option and return something to them such as “That wasn’t an option… what were you thinking?”
A bit old, but you can add "Default" as a keyword to the end of the switch statement (no quotes), with a default action that gets executed if none of the switch options match the input.
This is Awesome!
Thanks
Dan
I have a problem with my script, which matches closely to what is above. The first time I run it, I get the menu, make a "1" selection (get-mailbox), it pauses, but I get no results. If I press 1 again, THEN I get results. What I want it to do is give me results and pause at the end of those results so I can review them. I seemed to have narrowed this down to the "sort" option in my menu item. If I remove the sort, this all works. Any ideas?
function Show-Menu
{
param ([string]$Title = 'My Menu')
Clear-Host
Write-Host "================ Mailbox Report Options ================"
Write-Host "1: Press '1' for HC Mailboxes."
Write-Host "2: Press '2' for MC Mailboxes."
Write-Host "3: Press '3' for HP Mailboxes."
Write-Host "Q: Press 'Q' to quit."
Write-host "`n"
}
DO
{
Show-Menu –Title 'My Menu'
$input = Read-Host "Please make a selection"
switch ($input)
{
'1' {get-mailbox -OrganizationalUnit "ou=HC,OU=Domain Users,DC=contoso,DC=com" | get-mailboxstatistics | select displayname, totalitemsize | sort totalitemsize}
'2' {get-mailbox -OrganizationalUnit "ou=MC,OU=Domain Users,DC=contoso,DC=com" | get-mailboxstatistics | select displayname, totalitemsize | sort totalitemsize}
'3' {get-mailbox -OrganizationalUnit "ou=HP,OU=Domain Users,DC=contoso,DC=com" | get-mailboxstatistics | select displayname, totalitemsize | sort totalitemsize}
'q' {EXIT}
}
pause
}
until ($input -eq 'q')
John try using Format-Table in the place of Select
Is there a way to make it return to the main menu instead of quitting?
Adam, what do you mean by return to main menu? The article speaks about showing a menu and once a selection made, the selection is used by a switch further in the script.
Hopefully you are still monitoring this feedback and responding, I know this article is old. And please forgive my newness to PowerShell, I am a Linux guy diving head first into PowerShell.
I've created the script just prior to the do / until section. And that is where you lost me… And this might just be a super simple question, but like I said, I have been working with PowerShell for all of 3 days now…
My script thus far is as follows.
function Show-Menu
{
param (
[string]$Title = 'Select a profile'
)
Clear-Host
Write-Host "================ $Title ================"
Write-Host "1: Press '1' ARIZONA."
Write-Host "2: Press '2' COLORADO."
Write-Host "3: Press '3' FLORIDA."
Write-Host "3: Press '4' MONTANA."
Write-Host "3: Press '5' OHIO."
Write-Host "3: Press '6' TEXAS."
Write-Host "3: Press '7' WYOMING."
Write-Host "Q: Press 'Q' to quit."
}
Show-Menu –Title 'Select a profile'
$selection = Read-Host "Please make a selection"
switch ($selection)
{
'1' {
'You chose option #1 ARIZONA'
} '2' {
'You chose option #2 COLORADO'
} '3' {
'You chose option #3 FLORIDA'
} '4' {
'You chose option #4 MONTANA'
} '5' {
'You chose option #5 OHIO'
} '6' {
'You chose option #6 TEXAS'
} '7' {
'You chose option #7 WYOMING'
} 'q' {
return
}
}
Now I want the output of the script to just give the state name, and be held as a variable, let's just say $State
How would I go about just clipping out the segment I want, and assigning it to the variable in question?
You can also do something like this:
Hello,
Thank you for this very helpful script!
Now please, cold anyone advise, from this script, how you would trigger the following actions :
++ If highlight "option 1" menu, and press ok , the script will open a file located here :
++ If highlight "option 2" menu, and press ok , the script will open a file located here :
etc..
Many MANY thanks in anticipation!!
Anthony
I hope this helps you guys a bit.
I can't seem to update or edit my post as I made a small fix. Here is the updated version:
Further updated to this code can be found on GitHub here.