Creating a PowerShell Console Menu

I was looking to add a console-based menu for Koupi to allow workflow creators to give their users choices.

I have worked with PowerShell for years, and most of the time I needed to give users a choice, I either added it as an argument when running the script or used the classic "enter 1 for option A, 2 for option B" model. I've never liked either option, but they were good enough at the time.

So, I did like anyone would have done, and I googled how to create a PowerShell menu. I found very few examples of people creating interactive menus, but there were no tutorials, just code to download. So I took on the challenge of creating an interactive PowerShell menu from scratch and share the process with you.

Design Considerations

Like any good engineering project, let's start with a design doc to keep in mind when creating the script.

  1. Users shouldn't have to edit the code for the menu (requires input).

  2. Users should select the options using the up and down keyboard arrows, and press enter to select the desired option.

  3. When selecting a value, the menu should highlight the selected option line.

  4. The menu should return the selected value.

  5. The menu should not clear the console.

Pseudocode

I usually do this part in my head, but since it is an important part of the process, I figured I would highlight it:


1. Get the options from the user
2. Set the current selection to the first item in the list of options
3. Print all the lines in the console
4. Wait for Arrow Up or Arrow Down or Enter Keys to be pressed
    a. if Arrow up is pressed, store the new selected option position (current selection - 1)
    b. if Arrow Down is pressed, store the new selected option position (current selection + 1)
    c. Return the selected option
5. If the selection is out of bound, set it to the proper position (0 or # of options - 1)
6. Go back to #3

Skelton

Let's create a skeleton of our code now that we have the general idea down.

As you can see, this is a pretty good skeleton so far, we only have two non-trivial pieces to work on:

  1. Draw the Menu

  2. Read the Keyboard Input

Koupi allows you to create PowerShell scripts without needing to write a single line of code. Just add the steps you want to perform, fill in the blanks, download the script and run it. It's that easy. Give it a try here (It's free).

Reading the Keyboard Input

I know we labeled reading the keyboard input as number 1, but it's the easiest part so let's do that first.

Unlike most keys, Arrow Up, Arrow Down and Enter aren't keys that can easily be read by Read-Host so we are going to use another way to read keys: The host.


PowerShell has a built-in $host variable which represents the current PowerShell application. It has a property which represents the current host's user interface (that will be important later for the menu as well).

You can read more about readkey here and the options it takes here. Basically it reads the keyboard events, in this case it reads every time a key is pressed, and will wait for a key to be pressed to return a value.

Since Arrow Up, Arrow Down and Enter aren't characters, the only way to differentiate them is to use the keys' virtualkeycode which associated a number to each key on a keyboard, in this case, 38, 40 and 13 respectively.


Our updated code looks like this now:

That was easy. Now to the hard part: drawing the menu repeatedly without clearing the host.


Drawing the Menu - Part I

Drawing the menu is truly the hard part in all of this, but let's start simply with a Write-Menu function, just to write the menu.

What this function does is write the menu. You may notice $MenuItems and $MenuPrompt are there, that's because this function is in the bigger Get-MenuSelection function. It's not really needed anywhere else in a script hence the location.

Let's give this a shot:

Clearly we're on the right track, but there's something missing, namely overwriting the previous menu every time a key is pressed. Let's work on this next.


Drawing the Menu - Part II

So how do we overwrite the previous menu?

Well, if it was a single line, we could easily overwrite the line, but this is a little more complicated.

Thankfully our $host friend is back to help us. This time $host.UI.RawUI.CursorPosition will do the trick. Why is that?

Well, what happens when you write a line with Write-Host every time a character or line is written, the cursor is moved. The next instance of Write-Host will be written starting where the cursor currently is.

So, all we have to do now is store the initial cursor position and move it back up every time we write the menu as such:

Let's look at our final code:

Now let's see our menu in action:


Conclusion

Congratulation on creating your own menu! Now you can make a nice looking use interface for your script.

The menu will be available soon in Koupi, and it will be using this code, well slightly modified.

Next step: Well, besides signing up for Koupi, do you think you can create a menu with multiple selection?


Koupi allows you to create PowerShell scripts without needing to write a single line of code. Just add the steps you want to perform, fill in the blanks, download the script and run it. It's that easy. Give it a try here (It's free).


1,822 views4 comments

©2019-2020 by Bulles Technologies. Proudly created with Wix.com