In PowerShell, the primary means to get interactive input from a user is with the Read-Host cmdlet. There's nothing wrong with it but sometimes if you are using it in a graphical tool like the PowerShell ISE or VS Code you may not realize you are being prompted. Or perhaps you are building some other type of PowerShell-based tool where you would like something other than a console-based prompt. I thought I'd give a sneak peak at a function I will be adding to my PSScriptTools module that creates a graphical inputbox using WPF.
ManageEngine ADManager Plus - Download Free Trial
Exclusive offer on ADManager Plus for US and UK regions. Claim now!
In the past, you've probably written PowerShell code to use generate a VBScript style input box. I know I have several versions. When I wrote them they worked just fine. They still "work" but today with very high resolution monitors, I'm currently running a 4K monitor, anything that uses Windows Forms doesn't scale well. WPF on the other hand is designed to automatically scale and adjust. It doesn't care that I'm running a 4K screen.
The function I wrote, called Invoke-InputBox, works the same was as Read-Host. You can specify a prompt, enter something and the command writes it back to the pipeline. Although since this is a form, you can also specify a title. Here is the form with default values.
$p = Invoke-InputBox
Pressing OK will write the value in the text box to the pipeline and assign it to $p. I also added a parameter so that you can enter a secure string.
$s = Invoke-InputBox -Title "New Password" -Prompt "Enter a new password" -AsSecureString
I went "quick and dirty" and created a simple WPF form using a stack panel. There's no messy xaml. I think the code is pretty straightforward. I'll share the current version here, but look for it to eventually appear in the PSScriptTools module.
Function Invoke-InputBox { [cmdletbinding(DefaultParameterSetName="plain")] [OutputType([system.string],ParameterSetName='plain')] [OutputType([system.security.securestring],ParameterSetName='secure')] Param( [Parameter(ParameterSetName="secure")] [Parameter(HelpMessage = "Enter the title for the input box. No more than 25 characters.", ParameterSetName="plain")] [ValidateNotNullorEmpty()] [ValidateScript({$_.length -le 25})] [string]$Title = "User Input", [Parameter(ParameterSetName="secure")] [Parameter(HelpMessage = "Enter a prompt. No more than 50 characters.",ParameterSetName="plain")] [ValidateNotNullorEmpty()] [ValidateScript({$_.length -le 50})] [string]$Prompt = "Please enter a value:", [Parameter(HelpMessage = "Use to mask the entry and return a secure string.", ParameterSetName="secure")] [switch]$AsSecureString ) if ($PSEdition -eq 'Core') { Write-Warning "Sorry. This command will not run on PowerShell Core." #bail out Return } Add-Type -AssemblyName PresentationFramework Add-Type –assemblyName PresentationCore Add-Type –assemblyName WindowsBase #remove the variable because it might get cached in the ISE or VS Code Remove-Variable -Name myInput -Scope script -ErrorAction SilentlyContinue $form = New-Object System.Windows.Window $stack = New-object System.Windows.Controls.StackPanel #define what it looks like $form.Title = $title $form.Height = 150 $form.Width = 350 $label = New-Object System.Windows.Controls.Label $label.Content = " $Prompt" $label.HorizontalAlignment = "left" $stack.AddChild($label) if ($AsSecureString) { $inputbox = New-Object System.Windows.Controls.PasswordBox } else { $inputbox = New-Object System.Windows.Controls.TextBox } $inputbox.Width = 300 $inputbox.HorizontalAlignment = "center" $stack.AddChild($inputbox) $space = new-object System.Windows.Controls.Label $space.Height = 10 $stack.AddChild($space) $btn = New-Object System.Windows.Controls.Button $btn.Content = "_OK" $btn.Width = 65 $btn.HorizontalAlignment = "center" $btn.VerticalAlignment = "bottom" #add an event handler $btn.Add_click( { if ($AsSecureString) { $script:myInput = $inputbox.SecurePassword } else { $script:myInput = $inputbox.text } $form.Close() }) $stack.AddChild($btn) $space2 = new-object System.Windows.Controls.Label $space2.Height = 10 $stack.AddChild($space2) $btn2 = New-Object System.Windows.Controls.Button $btn2.Content = "_Cancel" $btn2.Width = 65 $btn2.HorizontalAlignment = "center" $btn2.VerticalAlignment = "bottom" #add an event handler $btn2.Add_click( { $form.Close() }) $stack.AddChild($btn2) #add the stack to the form $form.AddChild($stack) #show the form $inputbox.Focus() | Out-Null $form.WindowStartupLocation = [System.Windows.WindowStartupLocation]::CenterScreen $form.ShowDialog() | out-null #write the result from the input box back to the pipeline $script:myInput }
Because the function uses WPF, it will not work in PowerShell Core. In the meantime I hope some of you will try it out and let me know what you think.
This is perfect. I have been looking for a simple dialog box .
I have a script that automates the creation of custom SharePoint web applications and site collection. Currently I ask for the information at the command line which can be confusing for some admin who are not familiar with powershell.
I will try this out and let you know.
Thanks
This is exactly what I was looking for. Did the usual scouring the net with varying searches, although I wish it’d popped up first but hey ho.
Thank You.
Frankie