{"id":53043,"date":"2009-07-03T02:00:00","date_gmt":"2009-07-03T02:00:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2009\/07\/03\/hey-scripting-guy-how-can-i-prompt-users-for-information-when-a-script-is-run\/"},"modified":"2009-07-03T02:00:00","modified_gmt":"2009-07-03T02:00:00","slug":"hey-scripting-guy-how-can-i-prompt-users-for-information-when-a-script-is-run","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/hey-scripting-guy-how-can-i-prompt-users-for-information-when-a-script-is-run\/","title":{"rendered":"Hey, Scripting Guy! How Can I Prompt Users for Information When a Script Is Run?"},"content":{"rendered":"<h2><img decoding=\"async\" class=\"nearGraphic\" title=\"Hey, Scripting Guy! Question\" border=\"0\" alt=\"Hey, Scripting Guy! Question\" align=\"left\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/q-for-powertip.jpg\" width=\"34\" height=\"34\"> Hey, Scripting Guy! <span>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?<\/p>\n<p><\/span><\/p>\n<p>&#8211; MS<\/p>\n<p><img decoding=\"async\" border=\"0\" alt=\"Spacer\" src=\"https:\/\/devblogs.microsoft.com\/scripting\/wp-content\/uploads\/sites\/29\/2019\/05\/spacer.gif\" width=\"5\" height=\"5\"><img decoding=\"async\" class=\"nearGraphic\" title=\"Hey, Scripting Guy! Answer\" border=\"0\" alt=\"Hey, Scripting Guy! Answer\" align=\"left\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/a-for-powertip.jpg\" width=\"34\" height=\"34\"> <\/p>\n<p>Hi MS,<\/p>\n<p>There are lots of things that do not make sense to me: <a href=\"http:\/\/en.wikipedia.org\/wiki\/Burning_Man\"><font color=\"#0000ff\" face=\"Segoe\">Burning Man<\/font><\/a> 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 <a href=\"http:\/\/en.wikipedia.org\/wiki\/Goliath_grouper\"><font color=\"#0000ff\" face=\"Segoe\">goliath grouper<\/font><\/a> 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. <\/p>\n<p class=\"MsoNormal\"><img decoding=\"async\" title=\"Image of a goliath grouper\" alt=\"Image of a goliath grouper\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/hsg\/2009\/july\/hey0702\/hsg-07-02-09-01.jpg\" width=\"600\" height=\"452\"><\/p>\n<p class=\"MsoNormal\"><br>As you know, MS, scripts often require input.<span>&nbsp;<\/span>One reason a script needs input is to customize the information that is returned to the user. In VBScript you could use the <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ss1ysb2a(VS.85).aspx\"><font color=\"#0000ff\" face=\"Segoe\">WshArguments<\/font><\/a> object to obtain information from the command line. You could also use an input box. In Windows PowerShell, you have the <b>Read-Host<\/b> cmdlet that will allow you to prompt for information from the command line. This is seen here: <\/p>\n<p class=\"CodeBlockScreened\"><font size=\"1\"><font><font face=\"Lucida Sans Typewriter\">PS C:&gt; Read-Host &#8220;Type your name&#8221;<\/p>\n<p><\/font><\/font><\/font><\/p>\n<p class=\"CodeBlockScreened\"><font size=\"1\"><font><font face=\"Lucida Sans Typewriter\">type your name: ed<\/p>\n<p><\/font><\/font><\/font><\/p>\n<p class=\"CodeBlockScreened\"><font size=\"1\"><font><font face=\"Lucida Sans Typewriter\">ed<\/p>\n<p><\/font><\/font><\/font><\/p>\n<p class=\"CodeBlockScreened\"><font size=\"1\"><font><font face=\"Lucida Sans Typewriter\">PS C:&gt;<\/p>\n<p><\/font><\/font><\/font><\/p>\n<p class=\"MsoNormal\">&nbsp;<\/p>\n<p class=\"MsoNormal\">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&mdash;it will automatically be shown on the screen. This is seen here: <\/p>\n<p class=\"CodeBlock\"><font size=\"1\"><font face=\"Lucida Sans Typewriter\"><span>&#8220;Preparing to copy files to USB drive&#8221;<\/span><\/p>\n<p><\/font><\/font><\/p>\n<p class=\"MsoNormal\">Next we use the <b>Read-Host<\/b> cmdlet to display a message prompt on the screen. The first parameter of the <b>Read-Host<\/b> 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:<\/p>\n<p class=\"CodeBlock\"><font size=\"1\"><font face=\"Lucida Sans Typewriter\"><span>Read-Host &#8220;Ensure usb drive is in the computer. Press &lt;enter&gt; when ready to copy&#8221;<\/span><\/p>\n<p><\/font><\/font><\/p>\n<p class=\"MsoNormal\">When the script gets to the <b>Read-Host<\/b> cmdlet, it will halt execution of the script until ENTER is pressed. This is seen here:<\/p>\n<p class=\"MsoNormal\"><img decoding=\"async\" title=\"Image of user prompted to ensure USB drive is in computer\" alt=\"Image of user prompted to ensure USB drive is in computer\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/hsg\/2009\/july\/hey0702\/hsg-07-02-09-02.jpg\" width=\"600\" height=\"179\"><\/p>\n<p class=\"MsoNormal\"><br>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. <\/p>\n<p class=\"CodeBlockScreenedHead\"><strong>DemoPromptToCopy.ps1<\/p>\n<p><\/strong><\/p>\n<p class=\"CodeBlockScreened\"><font size=\"1\"><font><font face=\"Lucida Sans Typewriter\"><\/p>\n<p><\/font><\/font><\/font><\/p>\n<p class=\"CodeBlockScreened\"><font size=\"1\"><font><font face=\"Lucida Sans Typewriter\">&#8220;Preparing to copy files to USB drive&#8221;<\/p>\n<p><\/font><\/font><\/font><\/p>\n<p class=\"CodeBlockScreened\"><font size=\"1\"><font><font face=\"Lucida Sans Typewriter\">Read-Host &#8220;Ensure USB drive is in the computer. Press &lt;enter&gt; when ready to copy.&#8221;<\/p>\n<p><\/font><\/font><\/font><\/p>\n<p class=\"CodeBlockScreened\"><font size=\"1\"><font><font face=\"Lucida Sans Typewriter\">Copy-Item -path &#8220;C:fso&#8221; -destination &#8220;D:fso&#8221; -recurse<\/p>\n<p><\/font><\/font><\/font><\/p>\n<p>It is possible to expand on the capabilities of the <b>Read-Host<\/b> 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 <b>Switch<\/b> statement to evaluate the data that is returned from the command line. By using the <b>Switch<\/b> statement, you have the ability to use a regular expression pattern match to verify what is typed at the command line. <\/p>\n<p class=\"MsoNormal\">In the ReadHostQueryDrive.ps1 script, the <b>Read-Host<\/b> cmdlet is used to prompt the user to enter the drive letter that will be used to request volume information from WMI. The <b>Switch<\/b> statement is used to evaluate the value that is typed in response to the prompt. This time we must store the results of the <b>Read-Host<\/b> cmdlet into a variable. We use the <b>$response<\/b> variable for that job. The <b>Switch<\/b> statement uses the <b>&ndash;regex<\/b> parameter to use regular expressions to evaluate the value that is stored in the <b>$response<\/b> variable. If the data stored in the <b>$response<\/b> variable contains the letter &#8220;c&#8221; it will use the <b>Get-WmiObject<\/b> cmdlet to query the <b>Win32_Volume<\/b> WMI class for information on the &#8220;c&#8221; drive. If the string contained in the <b>$response<\/b> variable contains the letter &#8220;d&#8221; the script will query for information related to the &#8220;d&#8221; 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:<\/p>\n<p class=\"BullList\"><span><span>&middot;<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><\/span><\/span>C<\/p>\n<p class=\"BullList\"><span><span>&middot;<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><\/span><\/span>C:<\/p>\n<p class=\"BullList\"><span><span>&middot;<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><\/span><\/span>C:<\/p>\n<p class=\"MsoNormal\">This solves a problem that that often crops up when trying to use command-line utilities from the command line&mdash;how does the utility want the drive letter specified? The ReadHostQueryDrive.ps1 script is seen here. <\/p>\n<p class=\"CodeBlockScreenedHead\"><strong>ReadHostQueryDrive.ps1<\/p>\n<p><\/strong><\/p>\n<p class=\"CodeBlockScreened\"><font size=\"1\"><font><font face=\"Lucida Sans Typewriter\">$response = Read-Host &#8220;Type drive letter to query &lt;c: \/ d:&gt;&#8221;<br>Switch -regex($response) {<br><span>&nbsp; <\/span>&#8220;C&#8221; { Get-WmiObject -class Win32_Volume -filter &#8220;driveletter = &#8216;c:'&#8221; }<br><span>&nbsp; <\/span>&#8220;D&#8221; { Get-WmiObject -class Win32_Volume -filter &#8220;driveletter = &#8216;d:'&#8221; }<br>} #end switch<\/p>\n<p><\/font><\/font><\/font><\/p>\n<p class=\"MsoNormal\">A more elegant approach to requesting information from the user is to use the <b>$host.ui.PromptForChoice<\/b> class to handle the prompting. The <b>PromptForChoice<\/b> class uses the choices that are created by the <b>System.Management.Auomation.Host.ChoiceDescription<\/b> 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:<\/p>\n<p class=\"CodeBlock\"><font size=\"1\"><font face=\"Lucida Sans Typewriter\">$choices = [System.Management.Automation.Host.ChoiceDescription[]] `<\/p>\n<p><\/font><\/font><\/p>\n<p class=\"CodeBlock\"><font size=\"1\"><font face=\"Lucida Sans Typewriter\">@(&#8220;&amp;C:&#8221;, &#8220;&amp;D:&#8221;, &#8220;&amp;All&#8221;)<\/p>\n<p><\/font><\/font><\/p>\n<p class=\"MsoNormal\"><br>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 <b>PromptForChoice<\/b> class. This class needs the caption, the message, the choices and the default choice, as seen here: <\/p>\n<p class=\"CodeBlock\"><font size=\"1\"><font face=\"Lucida Sans Typewriter\"><span>$choiceRTN = $host.ui.PromptForChoice($caption,$message, $choices,$defaultChoice)<\/span><\/p>\n<p><\/font><\/font><\/p>\n<p class=\"MsoNormal\"><br>We use the <b>Switch<\/b> statement to evaluate the choice that is selected. This is seen here: <\/p>\n<p><font size=\"1\"><font face=\"Lucida Sans Typewriter\"><\/p>\n<p><p class=\"CodeBlock\">switch($choiceRTN)<\/p>\n<p class=\"CodeBlock\">{<\/p>\n<p class=\"CodeBlock\"><span>&nbsp;<\/span>0<span>&nbsp;&nbsp;&nbsp; <\/span>{ Get-WmiObject -class Win32_Volume -filter &#8220;driveletter = &#8216;c:'&#8221;<span>&nbsp; <\/span>}<\/p>\n<p class=\"CodeBlock\"><span>&nbsp;<\/span>1<span>&nbsp;&nbsp;&nbsp; <\/span>{ Get-WmiObject -class Win32_Volume -filter &#8220;driveletter = &#8216;d:'&#8221;<span>&nbsp; <\/span>}<\/p>\n<p class=\"CodeBlock\"><span>&nbsp;<\/span>2<span>&nbsp;&nbsp;&nbsp; <\/span>{ Get-WmiObject -class Win32_Volume<span>&nbsp; <\/span>}<span>}<\/span><\/p>\n<\/p>\n<p><\/font><\/font><\/p>\n<p class=\"CodeBlockScreenedHead\"><span>The complete PromptForChoice.ps1 script is seen here.<\/span><strong>&nbsp;<\/strong><\/p>\n<p class=\"CodeBlockScreenedHead\"><strong>PromptForChoiceQueryDrive.ps1<\/p>\n<p><\/strong><\/p>\n<p><font size=\"1\"><font face=\"Lucida Sans Typewriter\"><\/p>\n<p><p class=\"CodeBlock\">$caption = &#8220;Please select the drive to query&#8221;<\/p>\n<p class=\"CodeBlock\">$message = &#8220;Select drive to query&#8221;<\/p>\n<p class=\"CodeBlock\">$choices = [System.Management.Automation.Host.ChoiceDescription[]] `<\/p>\n<p class=\"CodeBlock\">@(&#8220;&amp;C:&#8221;, &#8220;&amp;D:&#8221;, &#8220;&amp;All&#8221;)<\/p>\n<p class=\"CodeBlock\">[int]$defaultChoice = 0<\/p>\n<p class=\"CodeBlock\">$choiceRTN = $host.ui.PromptForChoice($caption,$message, $choices,$defaultChoice)<\/p>\n<p class=\"CodeBlock\">\n<p>&nbsp;<\/p>\n<\/p>\n<p class=\"CodeBlock\">switch($choiceRTN)<\/p>\n<p class=\"CodeBlock\">{<\/p>\n<p class=\"CodeBlock\"><span>&nbsp;<\/span>0<span>&nbsp;&nbsp;&nbsp; <\/span>{ Get-WmiObject -class Win32_Volume -filter &#8220;driveletter = &#8216;c:'&#8221;<span>&nbsp; <\/span>}<\/p>\n<p class=\"CodeBlock\"><span>&nbsp;<\/span>1<span>&nbsp;&nbsp;&nbsp; <\/span>{ Get-WmiObject -class Win32_Volume -filter &#8220;driveletter = &#8216;d:'&#8221;<span>&nbsp; <\/span>}<\/p>\n<p class=\"CodeBlock\"><span>&nbsp;<\/span>2<span>&nbsp;&nbsp;&nbsp; <\/span>{ Get-WmiObject -class Win32_Volume<span>&nbsp; <\/span>}<\/p>\n<p class=\"CodeBlock\">}<\/p>\n<\/p>\n<p><\/font><\/font><\/p>\n<p class=\"MsoNormal\"><span><\/span>&nbsp;<\/p>\n<p class=\"MsoNormal\"><span>When the PromptForChoiceQueryDrive.ps1 script is run, these choices are displayed:<\/span>&nbsp;<\/p>\n<p class=\"MsoNormal\"><img decoding=\"async\" title=\"Image of choices displayed when script is run\" alt=\"Image of choices displayed when script is run\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/hsg\/2009\/july\/hey0702\/hsg-07-02-09-03.jpg\" width=\"600\" height=\"297\"><\/p>\n<p class=\"MsoNormal\"><br>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&rsquo;s right, it is time for Quick-Hits Friday! Until then, peace.<\/p>\n<p><b><span>Ed Wilson and Craig Liebendorfer, Scripting Guys<\/span><\/b><span><\/p>\n<p><\/span><\/p>\n<p>&nbsp;<\/p>\n<\/h2>\n","protected":false},"excerpt":{"rendered":"<p>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 [&hellip;]<\/p>\n","protected":false},"author":595,"featured_media":87096,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[2,3,4,45],"class_list":["post-53043","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-running","tag-scripting-guy","tag-scripting-techniques","tag-windows-powershell"],"acf":[],"blog_post_summary":"<p>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 [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/53043","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/users\/595"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/comments?post=53043"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/53043\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media\/87096"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media?parent=53043"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=53043"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=53043"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}