PowerShell Multi-Line Input Box Dialog, Open File Dialog, Folder Browser Dialog, Input Box, and Message Box
I love PowerShell, and when prompting users for input I often prefer to use GUI controls rather than have them enter everything into the console, as some things like browsing for files or folders or entering multi-line text aren’t very pleasing to do directly in the PowerShell prompt window. So I thought I’d share some PowerShell code that I often use for these purposes. Below I give the code for creating each type of GUI control from a function, an example of calling the function, and a screen shot of what the resulting GUI control looks like.
Download a file containing the code for the functions and examples shown here
Show a message box
Function:
# Show message box popup and return the button clicked by the user.
function Read-MessageBoxDialog([string]$Message, [string]$WindowTitle, [System.Windows.Forms.MessageBoxButtons]$Buttons = [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]$Icon = [System.Windows.Forms.MessageBoxIcon]::None)
{
Add-Type -AssemblyName System.Windows.Forms
return [System.Windows.Forms.MessageBox]::Show($Message, $WindowTitle, $Buttons, $Icon)
}
Example:
$buttonClicked = Read-MessageBoxDialog -Message "Please press the OK button." -WindowTitle "Message Box Example" -Buttons OKCancel -Icon Exclamation
if ($buttonClicked -eq "OK") { Write-Host "Thanks for pressing OK" }
else { Write-Host "You clicked $buttonClicked" }
Prompt for single-line user input
Function:
# Show input box popup and return the value entered by the user.
function Read-InputBoxDialog([string]$Message, [string]$WindowTitle, [string]$DefaultText)
{
Add-Type -AssemblyName Microsoft.VisualBasic
return [Microsoft.VisualBasic.Interaction]::InputBox($Message, $WindowTitle, $DefaultText)
}
Example:
$textEntered = Read-InputBoxDialog -Message "Please enter the word 'Banana'" -WindowTitle "Input Box Example" -DefaultText "Apple"
if ($textEntered -eq $null) { Write-Host "You clicked Cancel" }
elseif ($textEntered -eq "Banana") { Write-Host "Thanks for typing Banana" }
else { Write-Host "You entered $textEntered" }
Prompt for a file
This is based on a post the Scripting Guy made.
Function:
# Show an Open File Dialog and return the file selected by the user.
function Read-OpenFileDialog([string]$WindowTitle, [string]$InitialDirectory, [string]$Filter = "All files (*.*)|*.*", [switch]$AllowMultiSelect)
{
Add-Type -AssemblyName System.Windows.Forms
$openFileDialog = New-Object System.Windows.Forms.OpenFileDialog
$openFileDialog.Title = $WindowTitle
if (![string]::IsNullOrWhiteSpace($InitialDirectory)) { $openFileDialog.InitialDirectory = $InitialDirectory }
$openFileDialog.Filter = $Filter
if ($AllowMultiSelect) { $openFileDialog.MultiSelect = $true }
$openFileDialog.ShowHelp = $true # Without this line the ShowDialog() function may hang depending on system configuration and running from console vs. ISE.
$openFileDialog.ShowDialog() > $null
if ($AllowMultiSelect) { return $openFileDialog.Filenames } else { return $openFileDialog.Filename }
}
Example:
$filePath = Read-OpenFileDialog -WindowTitle "Select Text File Example" -InitialDirectory 'C:\' -Filter "Text files (*.txt)|*.txt"
if (![string]::IsNullOrEmpty($filePath)) { Write-Host "You selected the file: $filePath" }
else { "You did not select a file." }
Prompt for a directory
This is based on this post, as using System.Windows.Forms.FolderBrowserDialog
may hang depending on system configuration and running from the console vs. PS ISE.
Function:
# Show an Open Folder Dialog and return the directory selected by the user.
function Read-FolderBrowserDialog([string]$Message, [string]$InitialDirectory, [switch]$NoNewFolderButton)
{
$browseForFolderOptions = 0
if ($NoNewFolderButton) { $browseForFolderOptions += 512 }
$app = New-Object -ComObject Shell.Application
$folder = $app.BrowseForFolder(0, $Message, $browseForFolderOptions, $InitialDirectory)
if ($folder) { $selectedDirectory = $folder.Self.Path } else { $selectedDirectory = '' }
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($app) > $null
return $selectedDirectory
}
Example:
$directoryPath = Read-FolderBrowserDialog -Message "Please select a directory" -InitialDirectory 'C:\' -NoNewFolderButton
if (![string]::IsNullOrEmpty($directoryPath)) { Write-Host "You selected the directory: $directoryPath" }
else { "You did not select a directory." }
Prompt for multi-line user input
This is based on code shown in this TechNet article.
Function:
function Read-MultiLineInputBoxDialog([string]$Message, [string]$WindowTitle, [string]$DefaultText)
{
<#
.SYNOPSIS
Prompts the user with a multi-line input box and returns the text they enter, or null if they cancelled the prompt.
.DESCRIPTION
Prompts the user with a multi-line input box and returns the text they enter, or null if they cancelled the prompt.
.PARAMETER Message
The message to display to the user explaining what text we are asking them to enter.
.PARAMETER WindowTitle
The text to display on the prompt window's title.
.PARAMETER DefaultText
The default text to show in the input box.
.EXAMPLE
$userText = Read-MultiLineInputDialog "Input some text please:" "Get User's Input"
Shows how to create a simple prompt to get mutli-line input from a user.
.EXAMPLE
# Setup the default multi-line address to fill the input box with.
$defaultAddress = @'
John Doe
123 St.
Some Town, SK, Canada
A1B 2C3
'@
$address = Read-MultiLineInputDialog "Please enter your full address, including name, street, city, and postal code:" "Get User's Address" $defaultAddress
if ($address -eq $null)
{
Write-Error "You pressed the Cancel button on the multi-line input box."
}
Prompts the user for their address and stores it in a variable, pre-filling the input box with a default multi-line address.
If the user pressed the Cancel button an error is written to the console.
.EXAMPLE
$inputText = Read-MultiLineInputDialog -Message "If you have a really long message you can break it apart`nover two lines with the powershell newline character:" -WindowTitle "Window Title" -DefaultText "Default text for the input box."
Shows how to break the second parameter (Message) up onto two lines using the powershell newline character (`n).
If you break the message up into more than two lines the extra lines will be hidden behind or show ontop of the TextBox.
.NOTES
Name: Show-MultiLineInputDialog
Author: Daniel Schroeder (originally based on the code shown at http://technet.microsoft.com/en-us/library/ff730941.aspx)
Version: 1.0
#>
Add-Type -AssemblyName System.Drawing
Add-Type -AssemblyName System.Windows.Forms
# Create the Label.
$label = New-Object System.Windows.Forms.Label
$label.Location = New-Object System.Drawing.Size(10,10)
$label.Size = New-Object System.Drawing.Size(280,20)
$label.AutoSize = $true
$label.Text = $Message
# Create the TextBox used to capture the user's text.
$textBox = New-Object System.Windows.Forms.TextBox
$textBox.Location = New-Object System.Drawing.Size(10,40)
$textBox.Size = New-Object System.Drawing.Size(575,200)
$textBox.AcceptsReturn = $true
$textBox.AcceptsTab = $false
$textBox.Multiline = $true
$textBox.ScrollBars = 'Both'
$textBox.Text = $DefaultText
# Create the OK button.
$okButton = New-Object System.Windows.Forms.Button
$okButton.Location = New-Object System.Drawing.Size(415,250)
$okButton.Size = New-Object System.Drawing.Size(75,25)
$okButton.Text = "OK"
$okButton.Add_Click({ $form.Tag = $textBox.Text; $form.Close() })
# Create the Cancel button.
$cancelButton = New-Object System.Windows.Forms.Button
$cancelButton.Location = New-Object System.Drawing.Size(510,250)
$cancelButton.Size = New-Object System.Drawing.Size(75,25)
$cancelButton.Text = "Cancel"
$cancelButton.Add_Click({ $form.Tag = $null; $form.Close() })
# Create the form.
$form = New-Object System.Windows.Forms.Form
$form.Text = $WindowTitle
$form.Size = New-Object System.Drawing.Size(610,320)
$form.FormBorderStyle = 'FixedSingle'
$form.StartPosition = "CenterScreen"
$form.AutoSizeMode = 'GrowAndShrink'
$form.Topmost = $True
$form.AcceptButton = $okButton
$form.CancelButton = $cancelButton
$form.ShowInTaskbar = $true
# Add all of the controls to the form.
$form.Controls.Add($label)
$form.Controls.Add($textBox)
$form.Controls.Add($okButton)
$form.Controls.Add($cancelButton)
# Initialize and show the form.
$form.Add_Shown({$form.Activate()})
$form.ShowDialog() > $null # Trash the text of the button that was clicked.
# Return the text that the user entered.
return $form.Tag
}
Example:
$multiLineText = Read-MultiLineInputBoxDialog -Message "Please enter some text. It can be multiple lines" -WindowTitle "Multi Line Example" -DefaultText "Enter some text here..."
if ($multiLineText -eq $null) { Write-Host "You clicked Cancel" }
else { Write-Host "You entered the following text: $multiLineText" }
All of these but the multi-line input box just use existing Windows Forms / Visual Basic controls.
I originally was using the Get verb to prefix the functions, then switched to the Show verb, but after reading through this page, I decided that the Read verb is probably the most appropriate (and it lines up with the Read-Host cmdlet).
Hopefully you find this useful.
Happy coding!
Comments
Richard
Hi,
Great script. One remark though. I am using this in a script of my own (or the intention is there). I get the input into a variable which I am going to use as the Body for an email i’m sending. However no carriage return are carried over so the message in the email is a single line. Any idea.
RvN
Richard
never mind. ;-) fixed
Jeremy
Thanks for an excellent file select function as well as the link back to the scripting guys post. I read their page, but your ready-to-go example worked better for me than theirs. Cheers
Powershell Multi-Line Input Box Dialog, Open File Dialog, Folder Browser Dialog, Input Box, and Message Box | psjjw
[…] https://blog.danskingdom.com/powershell-multi-line-input-box-dialog-open-file-dialog-folder-browser-dialog-input-box-and-message-box/ […]
Derrick B.
Great information!!! How do I tell the input script where to place the information thats being entered?
deadlydog
@Derrick B. Hey Derrick, I didn’t fully understand your question (not enough info), but I’ve updated the post with an example of using each function. Let me know if you still have questions.
Derrick B.
@deadlydog
Sorry about that. I’m a newbbie by far. I’ve created a script to add and setup apps within Citrix, but I was looking for something like a popup box to add to the code to answer the questions in the script. Looking at “Prompt for simple user input” looks like it will do the trick. What don’t understand is how to add that to what I have to input the text in the right field. Can you show an example?
SeanD
Not sure how to insert this into my script. I have a script that looks at a text file (pc names), ping them and exports to a csv with the responses. Script work fine. I would like to prompt the user fot the text file instead of having the path hard coded. I tried pasting your sample variable $filepath in front of my code but it says i did not pick a file.
$filePath = Read-OpenFileDialog -WindowTitle “Select Text File Example” -InitialDirectory ‘C:' -Filter “Text files (.txt)|.txt” if (![string]::IsNullOrEmpty($filePath)) { Write-Host “You selected the file: $filePath” } else { “You did not select a file.” } get-content $filePath
$Output2 = “c:\PSexport\PingOldPCs5.csv”
Write-host ` “Pinging List of Dead Computers and Writing to c:\Psexport\PingPC.csv `n WAIT” -foregroundcolor “green” $filePath | ForEach-Object {GWMI win32pingstatus -filter (“address=’”+ $ +”’”) -computername .} | Select-Object ProtocolAddress,address,responsetime,statuscode | export-csv $Output2 -NoTypeInformation c:\PSexport\PingOldPCs5.csv
deadlydog
@SeanD You will also need to copy and paste the Read-OpenFileDialog function into your script as well, before calling it.
SeanD
OK. I think i am getting further. FYI - I am not a programmer but an admin learning PS.
My script pings the list of PCs that are in the text file. I am getting a blank excel sheet where normally if i hard code the text file location For-eachobject does its job and pings.
It seems like the function is just passing the name of the file
SeanD
Get-content was the trick. In case anyone wants to know - Here is the complete code that will allow you to pick a file and then read whats in it. Mine here reads it then pings the list
$filePath = Read-OpenFileDialog -WindowTitle “Select Text File Example” -InitialDirectory ‘C:' -Filter “Text files (.txt)|.txt” if (![string]::IsNullOrEmpty($filePath)) { Write-Host “You selected the file: $filePath” } else { “You did not select a file.” }
$Output2 = “c:\PSexport\PingOldPCs5.csv”
Show an Open File Dialog and return the file selected by the user.
function Read-OpenFileDialog([string]$WindowTitle, [string]$InitialDirectory, [string]$Filter = “All files (.)|.”, [switch]$AllowMultiSelect) { Add-Type -AssemblyName System.Windows.Forms $openFileDialog = New-Object System.Windows.Forms.OpenFileDialog $openFileDialog.Title = $WindowTitle if (![string]::IsNullOrWhiteSpace($InitialDirectory)) { $openFileDialog.InitialDirectory = $InitialDirectory } $openFileDialog.Filter = $Filter if ($AllowMultiSelect) { $openFileDialog.MultiSelect = $true } # openFileDialog.ShowHelp = $true # Without this line the ShowDialog() function may hang depending on system configuration and running from console vs. ISE. $openFileDialog.ShowDialog() > $null if ($AllowMultiSelect) { return $openFileDialog.Filenames } else { return $openFileDialog.Filename } } # End Function
$responses = @()
ForEach ($path in $filePath) {
}
Matthew
@Richard How did you end up getting the carriage returns to work?
Harry
Nice work on the scripts bro! they fit nicely into the one I’m developing at work to automate admin tasks over lots of pc’s
sergueik
Check my article on code project for a big number of relevant examples…
DemoD
When I run this from Powershell ISE the windows that pop up always end up behind the ISE. Is there any way to code and always have them show up in the foreground?
serguei kouzmine
$openFileDialog.Topmost = $True
deadlydog
@DemoD The only one that does not pop in the foreground for me is the Read-FolderBrowserDialog, and unfortunately I haven’t been able to find a way to force it. Luckily though it does create a new window icon in the start menu bar, so it’s at least a little obvious that a new popup was created and requires attention. If I do find a method that does it, I’ll update the post.
deadlydog
@serguei kouzmine Topmost is not a valid property on the $openFileDialog object, so your code generates an error. Also, the Read-OpenFileDialog function does not have the problem in my testing, so that code is not even required.
Aymen
When running the script I get an error message
Read-MessageBoxDialog: Unable to find type [System.Windows.Forms.MessageBoxButtons]. Make sure that the assembly that contains this type is loaded.
Any idea how to fix it?
deadlydog
@Aymen Move the line:
Add-Type -AssemblyName System.Windows.Forms
from within the Read-MessageBoxDialog function to just before it, so it looks like this:
Add-Type -AssemblyName System.Windows.Forms function Read-MessageBoxDialog([string]$Message, [string]$WindowTitle, [System.Windows.Forms.MessageBoxButtons]$Buttons = [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]$Icon = [System.Windows.Forms.MessageBoxIcon]::None) { return [System.Windows.Forms.MessageBox]::Show($Message, $WindowTitle, $Buttons, $Icon) }
I don’t have that problem on my local PC, so I’m guessing it’s a PowerShell 2.0 problem maybe?
Aymen
With this change it worked.
I have PowerShell 4.0 installed.
By the way: did you mean in the comments that the help button in the file selection dialog box is obligatory although it does nothing here?
Eric
I am trying to use the Prompt for a directory script. It worked a few days then now I get the following error when I run the script: “The term ‘Read-FolderBrowserDialog’ is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.”
I did a copy and paste directory from the code listed on this site so not sure what else is needed.
deadlydog
@Eric You will need to make sure the Read-FolderBrowserDialog function is defined in your script before you try and call it; so the function should be at the top of your script, and the line that calls is should be below that.
Eric
This is what I have :
#Opens file directory search $directoryPath = Read-FolderBrowserDialog -Message “Please select a directory” -InitialDirectory ‘S:\Projects\UCG\Production' -NoNewFolderButton if (![string]::IsNullOrEmpty($directoryPath)) { Write-Host “You selected the directory: $directoryPath” } else { “You did not select a directory.” }
#Search files within directory REST OF SCRIPT……..
Somehow this worked for a few days and when I closed saved the script and closed powershell the next time I tried to run it I got the error
deadlydog
@Eric Yeah, you had probably already ran the code that defined the Read-FolderBrowserDialog function, so the function was defined in your powershell session, even if you removed the actual code from your script. Then once you closed your powershell window then your session ended. All you need to do is put the function code at the top of your script.
e.g.
Show an Open Folder Dialog and return the directory selected by the user.
function Read-FolderBrowserDialog([string]$Message, [string]$InitialDirectory, [switch]$NoNewFolderButton) { $browseForFolderOptions = 0 if ($NoNewFolderButton) { $browseForFolderOptions += 512 }
#Opens file directory search $directoryPath = Read-FolderBrowserDialog -Message “Please select a directory” -InitialDirectory ‘S:\Projects\UCG\Production\’ -NoNewFolderButton if (![string]::IsNullOrEmpty($directoryPath)) { Write-Host “You selected the directory: $directoryPath” } else { “You did not select a directory.” }
#Search files within directory REST OF SCRIPT……..
Automating A Simple Go-lang Development Environment with Chocolatey | Manoel Carvalho's blog
[…] https://blog.danskingdom.com/powershell-multi-line-input-box-dialog-open-file-dialog-folder-browser-dialog-input-box-and-message-box/ […]
Kanaka
Very helpful article. Thank you
Varia
Finally found working snippet for powershell v2 to open a dialog to select a file. Many thanks!
Mike
You’ve saved my life. Thanks so much.
blaughw
I’ve used your single-line and file dialog snippets to make a “consumable” script for setting Exchange OOF messages for my org’s service desk. Very helpful, thank you!
Daniel
The multi-line user prompt is fantastic, but how do you run a ‘for each’ loop against each row entered into that prompt? It seems to take the input as one long string.
deadlydog
@Daniel Simply split the string on the newline character (
r
n) and then foreach over it. This stack overflow post shows how to do split a string on spaces; just swap the space out for the newline character, and the hard-coded string value for the string variable containing the user’s input. http://stackoverflow.com/a/11348779/602585Graham J
First off thanks for this, been using it for loads of Service Desk scripts.
Mind if I pick your brains on something?
Is there anyway of getting -DEFAULTTEXT to spread onto more than one line when reading from a variable or text file?
My variable is $OOO
“I am out of the office from x to y.
In my absence please contact z.
Thanks”
As a work around I’ve exported $OOO to a text file with the correct formatting. When I set the -DEFAULTTEXT to : -DEFAULTTEXT ( Get-Content C:\OOO.txt ) It displays as with double spacing as shown below.
“I am out of the office from x to y. In my absence please contact z. Thanks”
Any help would be appreciated. Thanks
deadlydog
@Graham J I’m not certain about when reading from a file, but for a variable you can just use the regular
r
n to denote a new line (the string must be in double quotes though, not single quotes) or you can use the [Environment]::NewLine character.For example, the following will have the default message show up over 3 lines:
$text = “Some text on line 1
r
nthis is on line 2 (multiple lines)” + [Environment]::NewLine + “and some more text on line 3” Read-MultiLineInputBoxDialog -Message ‘The message’ -WindowTitle ‘Window title’ -DefaultText $textWhen reading the text in from a file, I suspect you may need to do a string replacement on the text that it read in, and replace whatever characters it sees for the new line character with
r
n.devenir riche
An outstanding share! I’ve just forwarded this onto a co-worker who had been conducting a little research on this. And he actually ordered mme lunch simply because I discovered it for him…
lol. So let me reword this…. Thank YOU for the meal!! But yeah, thanx for spending the time to discuss this isue here on your web site.
MikeM
This is an extraordinary post! Thanks for taking the time to put this together and sharing.
MM
Andres
I’m passing through a multiline $DefaultText that’s basically notes coming from VM’s. I’m seeing multilines if I Write-Host $DefaultText inside the function. But When the text box is opened the lines are all one single line. If I press ok and output the $multiLineText it looks correct. Is there something else I need to do in order to make the multilines show up in $DefaultText inside $texBox.Text ?
deadlydog
@Andres Hmmm, I’m not certain. I guess one question I would have is are the VMs Windows or Linux? As I know Linux just uses \n for a new line, but Windows uses \r\n. I’m not certain if this is the problem or not, as I haven’t done any testing; this is just off the top of my head.
farah magbutay
Hi Daniel, great article. Ive got some questions regarding this. I have got quite similar code on opening a dialogbox. Ive got some dilemna though which I cant find an answer on. I am using powershell to test a form (Application form) via a webpage. However I have one mandatory field that needs a file to be uploaded hence a pop up box to choose a file to upload comes up. I get to a point where in it opens the dialog box and the cursor is on the filename field but how can I get the filename into the text box. HELP =) farah
Enzo Lopez
How can I create and array from the word in the $textBox.Text If I create an input box and the user enters “warning”, I then want an array that equals $warning for me to use later in the script. I’m able to get it type out, but how do I reference an array where the name of the array is unknown
$test = “`$” + $textBox.Text $magic = (,$test)
PS C:\Users> $magic $warning
my goal is the have something like this in the script $magic.ToString() = Get-Service and $warning should return whatever is in get-service
Enzo Lopez
@Enzo Lopez I figured it out
New-Variable -Name $textBox.Text Set-Variable -Name $textBox.Text -Value (get-service) -Scope global $ArrayName = “`$” + $textBox2.Text Write-Host “The Array name is $ArrayName”
Hoang
Hi Daniel, Great and very helpful article. I need your help with Prompt for single-line user input. Me scenario is prompting user to enter computername then it will check if that computername exist in the path, if not it’ll prompt again asking user to reenter the correct computername. However, after user entered correct computername, inputbox still comes up. Here is what I have:
Show input box popup and return the value entered by the user.
function Get-InputBoxDialog([string]$Message, [string]$WindowTitle) { Add-Type -AssemblyName Microsoft.VisualBasic return [Microsoft.VisualBasic.Interaction]::InputBox($Message, $WindowTitle) }
$OSDComputerName = Get-InputBoxDialog -Message “Enter OLD ComputerName” -WindowTitle “Source PC” $SrcPath = “\Server\Migfolder$OSDComputerName” do { $OSDComputerName = Get-InputBoxDialog -Message “OLD ComputerName not found. Re-Enter OLD ComputerName” -WindowTitle “Source PC” } until (Test-Path $SrcPath)
deadlydog
@Hoang Changing your code to the following should fix up your issue. In the future, please consider asking these types of questions in StackOverflow.com or a similar site rather than here. Thanks.
Show input box popup and return the value entered by the user.
function Get-InputBoxDialog([string]$Message, [string]$WindowTitle) { Add-Type -AssemblyName Microsoft.VisualBasic return [Microsoft.VisualBasic.Interaction]::InputBox($Message, $WindowTitle) }
do { $OSDComputerName = Get-InputBoxDialog -Message “Enter OLD ComputerName” -WindowTitle “Source PC” $SrcPath = “\Server\Migfolder$OSDComputerName” } until (Test-Path $SrcPath)
The problem was you were not rebuilding $SrcPath after getting the new $OSDComputerName value.
Adrian Sullivan
Super helpful. Thanks Daniel.
Leave a Comment
Your email address will not be published. Required fields are marked *