Hey, Scripting Guy! How Can I Prompt Users for Information When a Script Is Run?

ScriptingGuy1

Hey, Scripting Guy! Question Hey, Scripting Guy! I would like to have my script prompt the user for information when it is run. But I would like the person running the script to be able to supply more than one piece of information when the script is run. For example, I would like to provide information about hard drives on the computer, but I do not want to list all of the drives. I would like the user to be able to select one specific drive on the computer. Does this make sense?

– MS

SpacerHey, Scripting Guy! Answer

Hi MS,

There are lots of things that do not make sense to me: Burning Man is a good example; however, your request makes perfectly good sense. It does indeed seem like a good idea to be able to provide a user of your script the ability to make choices, or to supply a variety of information to your script when it is launched. This goliath grouper I saw while scuba diving off the coast of Little Cayman also seems to have some good ideas. He likes to hang out under coral ledges and wait for crustaceans, small fish, or even an octopus when he can find one.

Image of a goliath grouper


As you know, MS, scripts often require input. One reason a script needs input is to customize the information that is returned to the user. In VBScript you could use the WshArguments object to obtain information from the command line. You could also use an input box. In Windows PowerShell, you have the Read-Host cmdlet that will allow you to prompt for information from the command line. This is seen here:

PS C:> Read-Host “Type your name”

type your name: ed

ed

PS C:>

 

If you prompt for information, but do not save the information that is returned, all you have done is halt the execution of the script. However, this can be effectively used. For example, if you save a script that will copy files to a USB drive, you may wish to prompt the user to ensure the USB drive is connected before continuing. It might look something like the DemoPromptToCopy.ps1 script. In the DemoPromptToCopy.ps1 script, we first display a string that states we are getting ready to copy some files to a USB drive. To do this, we place the string in quotation marks—it will automatically be shown on the screen. This is seen here:

“Preparing to copy files to USB drive”

Next we use the Read-Host cmdlet to display a message prompt on the screen. The first parameter of the Read-Host cmdlet is the prompt parameter. We leave it off here, because the command is easy to read and to understand without it. This is seen here:

Read-Host “Ensure usb drive is in the computer. Press <enter> when ready to copy”

When the script gets to the Read-Host cmdlet, it will halt execution of the script until ENTER is pressed. This is seen here:

Image of user prompted to ensure USB drive is in computer


The last thing the DemoPromptToCopy.ps1 script does is copy a directory from the C: drive to the D: drive. The complete DempPromptToCopy.ps1 script is seen here.

DemoPromptToCopy.ps1

“Preparing to copy files to USB drive”

Read-Host “Ensure USB drive is in the computer. Press <enter> when ready to copy.”

Copy-Item -path “C:fso” -destination “D:fso” -recurse

It is possible to expand on the capabilities of the Read-Host cmdlet by saving the results from the cmdlet in a variable. After you have done this, you have a wide range of things you can do. One of my favorite Windows PowerShell scripting techniques is to use the Switch statement to evaluate the data that is returned from the command line. By using the Switch statement, you have the ability to use a regular expression pattern match to verify what is typed at the command line.

In the ReadHostQueryDrive.ps1 script, the Read-Host cmdlet is used to prompt the user to enter the drive letter that will be used to request volume information from WMI. The Switch statement is used to evaluate the value that is typed in response to the prompt. This time we must store the results of the Read-Host cmdlet into a variable. We use the $response variable for that job. The Switch statement uses the –regex parameter to use regular expressions to evaluate the value that is stored in the $response variable. If the data stored in the $response variable contains the letter “c” it will use the Get-WmiObject cmdlet to query the Win32_Volume WMI class for information on the “c” drive. If the string contained in the $response variable contains the letter “d” the script will query for information related to the “d” drive. The big advantage of the ReadHostQueryDrive.ps1 script is it allows the user to type in a wide variety of responses such as the following:

·         C

·         C:

·         C:

This solves a problem that that often crops up when trying to use command-line utilities from the command line—how does the utility want the drive letter specified? The ReadHostQueryDrive.ps1 script is seen here.

ReadHostQueryDrive.ps1

$response = Read-Host “Type drive letter to query <c: / d:>”
Switch -regex($response) {
  “C” { Get-WmiObject -class Win32_Volume -filter “driveletter = ‘c:'” }
  “D” { Get-WmiObject -class Win32_Volume -filter “driveletter = ‘d:'” }
} #end switch

A more elegant approach to requesting information from the user is to use the $host.ui.PromptForChoice class to handle the prompting. The PromptForChoice class uses the choices that are created by the System.Management.Auomation.Host.ChoiceDescription class. Because the choice descriptions are an array, we use array notation to specify the different choices. When creating the choice descriptions, each choice is preceded by the ampersand and stored in an array. This is seen here:

$choices = [System.Management.Automation.Host.ChoiceDescription[]] `

@(“&C:”, “&D:”, “&All”)


Next we create a variable that is used to specify the default choice. Because it is an array, each value has numeric value that begins counting a 0. Now that we have both the choices created and the default choice identified, it is time to create the PromptForChoice class. This class needs the caption, the message, the choices and the default choice, as seen here:

$choiceRTN = $host.ui.PromptForChoice($caption,$message, $choices,$defaultChoice)


We use the Switch statement to evaluate the choice that is selected. This is seen here:

switch($choiceRTN)

{

 0    { Get-WmiObject -class Win32_Volume -filter “driveletter = ‘c:'”  }

 1    { Get-WmiObject -class Win32_Volume -filter “driveletter = ‘d:'”  }

 2    { Get-WmiObject -class Win32_Volume  }}

The complete PromptForChoice.ps1 script is seen here. 

PromptForChoiceQueryDrive.ps1

$caption = “Please select the drive to query”

$message = “Select drive to query”

$choices = [System.Management.Automation.Host.ChoiceDescription[]] `

@(“&C:”, “&D:”, “&All”)

[int]$defaultChoice = 0

$choiceRTN = $host.ui.PromptForChoice($caption,$message, $choices,$defaultChoice)

 

switch($choiceRTN)

{

 0    { Get-WmiObject -class Win32_Volume -filter “driveletter = ‘c:'”  }

 1    { Get-WmiObject -class Win32_Volume -filter “driveletter = ‘d:'”  }

 2    { Get-WmiObject -class Win32_Volume  }

}

 

When the PromptForChoiceQueryDrive.ps1 script is run, these choices are displayed: 

Image of choices displayed when script is run


Well, MS, we hope we have given you some ideas you can use to elicit information from the people who use your scripts. This also concludes Input Week on the Script Center. Join us tomorrow as we open the mail bag and look at questions that do not require such a long explanation. That’s right, it is time for Quick-Hits Friday! Until then, peace.

Ed Wilson and Craig Liebendorfer, Scripting Guys

 

0 comments

Discussion is closed.

Feedback usabilla icon