Working with Interactive Prompts in PowerShell

March 25, 2018 Security and Compliance, MOVEit

In this PowerShell tutorial, we will cover a few ways to interactively prompt a user for input.

PowerShell is a powerful scripting language that can get a lot done, but it's not telepathic. Unless you provide instructions for what you need to be done in your script, PowerShell's not going to know if you meant file path A, file path B, a virtual machine named DC or if you want to really shut down an entire data center.

It's always a good idea to separate out these "questions" from your code logic in the form of parameters. By providing parameter input, the user can insert his/her own values into the code without actually changing anyway. However, the user must remember to use parameters and parameters cannot be used once inside of a script or function. To provide input a script or function, we can use another way known as interactive prompting.

There are a few ways to interactively prompt a user for input which we'll discuss.

  • Mandatory parameters
  • Read-Host
  • The PromptForChoice .NET method

Related: Building PowerShell Scripts To Tie Disparate Products Together

Inputting Mandatory Parameters

When you've written a function or script with a parameter, this parameter can be made to require a value before the script runs known as mandatory. For example, below is a function that forces the user to input a parameter before proceeding:

function Start-Server {
    param(
        [Parameter(Mandatory)]
        [string]$Name
    )
    Write-Output "Server name $Name was started"
}

When this function is run without using the Name parameter, you'll see something like below forcing you to input a value. Here we're stopping script execution to gather up values interactively from the user.

PS> Start-Server

cmdlet Start-Server at command pipeline position 1
Supply values for the following parameters:
Name:
 

Read-Host to Drive Interactive Prompts

PowerShell has a command that stops script execution and asks for value that can be inserted anywhere in a script known as Read-Host. When this command is executed inside of a script, it will stop execution, present an optional prompt in the console and accept an input from the user. Read-Host is great at gathering up values as the script is running and then assigning those values to variables. Using our example above, maybe I want to give the user the ability to delay the start of the server by X seconds. I've decided to prompt for a seconds value using Read-Host as shown below.

function Start-Server { param( [Parameter(Mandatory)][string]$Name ) $DelayinSeconds = Read-Host -Prompt 'How manys seconds to delay until server starts?' Write-Output "Server name $Name will be delayed by $DelayInSeconds seconds." } ```

I now run this function and see the following:

PS> Start-Server

cmdlet Start-Server at command pipeline position 1
Supply values for the following parameters:
Name: MyServer
How many seconds to delay until server starts?: 10
Server name MyServer will be delayed by 10 seconds.

Notice that using Read-Host is always mandatory. There's no way to provide a default value like there is by using parameters.

The PromptForChoice .NET Method

Finally, we have a method not native to PowerShell, but to .NET. This method uses the System.Management.Automation.Host.ChoiceDescription object and is used for building Yes/No questions for input.

Again using the example above, I'd like to give the user the choice to input the delay or not. If they just want to start the server immediately, the script will happily continue and do as directed. I need to add an interactive prompt to ask the user if they'd like to set a delay or not. Below is how we can make that happen.

function Start-Server {
    param(
        [Parameter(Mandatory)]
        [string]$Name
    )

    $yes = New-Object System.Management.Automation.Host.ChoiceDescription '&Yes', 'Allows setting a delay'
    $no = New-Object System.Management.Automation.Host.ChoiceDescription '&No', 'Does not allow setting a delay'
    $options = [System.Management.Automation.Host.ChoiceDescription[]]($yes, $no)
    $result = $host.ui.PromptForChoice('Set Delay?', 'Would you like to set a delay?', $options, 0)

    switch ($result)
        {
            0 {
                $DelayinSeconds = Read-Host -Prompt 'How manys seconds to delay until server starts?'
                $message = "Server name $Name will be delayed by $DelayInSeconds seconds."
            }
            1 {
                $message = "Server name $Name will not be delayed."
            }
        }
    Write-Output $message
}

Executing this function would give you:

PS> Start-Server

cmdlet Start-Server at command pipeline position 1
Supply values for the following parameters:
Name: MyServer
Set Delay?
Would you like to set a delay?
[Y] Yes  [N] No  [?] Help (default is "Y"): n
Server name MyServer will not be delayed.

Notice that we automatically got the [Y] Yes  [N] No  [?] Help (default is "Y"): line without building it ourselves. Here we're using the native capabilities of the PromptForChoice method to give the user a native-looking option experience.

 

Adam Bertram

Adam Bertram is a 25+ year IT veteran and an experienced online business professional. He’s a successful blogger, consultant, 6x Microsoft MVP, trainer, published author and freelance writer for dozens of publications. For how-to tech tutorials, catch up with Adam at adamtheautomator.com, connect on LinkedIn or follow him on X at @adbertram.

Read next Using the New MOVEit 2018 REST API with PowerShell