In the previous parts, we successfully displayed a custom TUI user interface in PowerShell 7, but it did not respond to user interactions and essentially caused the application to hang.
Responding to user input in TUI works much like in traditional graphical GUIs: you need to add event handlers to the elements of the window that receive user input.
Here is a revised script that demonstrates a simple TUI interface. It now responds to a button click (displaying a text-based second dialog) and closes the window when the user presses ESC:
#requires -version 7
#region Load TUI Binaries
$module = (Get-Module Microsoft.PowerShell.ConsoleGuiTools -List).ModuleBase
$exists = Test-Path -Path $module -PathType Container
if (!$exists) {
throw "TUI module not found. Did you install 'Microsoft.PowerShell.ConsoleGuiTools' from PowerShell Gallery yet?"
}
Add-Type -Path (Join-Path $module Terminal.Gui.dll)
#endregion
#region Sample TUI Window
[Terminal.Gui.Application]::Init()
$Window = [Terminal.Gui.Window]::new()
$Window.Title = 'Hello, World'
$Button = [Terminal.Gui.Button]::new()
$Button.Text = 'Button'
$Window.Add($Button)
# Adding event handlers (NEW)
# handle custom button
$Button.add_Clicked({ [Terminal.Gui.MessageBox]::Query('Hello', 'You clicked the button!') })
# handle closing window by pressing ESC
[Terminal.Gui.Application]::Top.add_KeyPress({
param($e)
if ($e.KeyEvent.Key -eq [Terminal.Gui.Key]::Esc) {
[Terminal.Gui.Application]::RequestStop()
}
})
[Terminal.Gui.Application]::Top.Add($Window)
[Terminal.Gui.Application]::Run()
#endregion
# clean up
[Terminal.Gui.Application]::Shutdown()
The code now gracefully cleans up the terminal window and frees memory by calling Shutdown() when it finishes.
Note: When you run the code inside a native PowerShell 7 console, it responds to mouse events. You can simply click the button to trigger its event handler. Without mouse support, press the highlighted keyboard shortcut (in this case, B). To close the secondary dialog, press ESC.
Creating Custom Dialog
Let’s put the learning points together and create a fully functional login dialog:
#requires -version 7
#region Load TUI Binaries
$module = (Get-Module Microsoft.PowerShell.ConsoleGuiTools -List).ModuleBase
$exists = Test-Path -Path $module -PathType Container
if (!$exists) {
throw "TUI module not found. Did you install 'Microsoft.PowerShell.ConsoleGuiTools' from PowerShell Gallery yet?"
}
# ignore errors in case the DLL was already loaded
Add-Type -Path (Join-Path $module Terminal.Gui.dll) -ErrorAction Ignore
#endregion
#region Sample TUI Window
[Terminal.Gui.Application]::Init()
#############DESIGN UI ELEMENTS####################
# later reveals whether user cancelled dialog
$canceled = $true
$window = [Terminal.Gui.Window] @{
Title = 'Get-TuiCredential'
Width = 45
Height = 9
X = [Terminal.Gui.Pos]::Center()
Y = [Terminal.Gui.Pos]::Center()
}
[Terminal.Gui.Application]::Top.Add($Window)
$labelUserName = [Terminal.Gui.Label] @{
Text = 'UserName'
X = 1
Y = 1
}
$window.Add($labelUserName)
$txtUserName = [Terminal.Gui.TextField]@{
Width = 30
X = 10
Y = 1
TabIndex = 1
}
$window.Add($txtUserName)
$labelPassword = [Terminal.Gui.Label] @{
Text = 'Password'
X = 1
Y = 3
}
$window.Add($labelPassword)
$txtPassword = [Terminal.Gui.TextField]@{
Width = 30
X = 10
Y = 3
TabIndex = 0
Secret = $True
}
$window.Add($txtPassword)
$btnLogin = [Terminal.Gui.Button]@{
Text = '_Login'
X = 7
Y = 5
TabIndex = 2
}
$window.Add($btnLogin)
$btnCancel = [Terminal.Gui.Button]@{
Text = '_Cancel'
X = $btnLogin.X + 9
Y = 5
TabIndex = 3
}
$window.Add($btnCancel)
$btnShow = [Terminal.Gui.Button]@{
Text = '_ShowPwd'
X = $btnCancel.X + 12
Y = 5
TabIndex = 4
}
$window.Add($btnShow)
#############ADD EVENTS TO UI ELEMENTS#############
# handle custom buttons
$btnLogin.add_Clicked({
$script:canceled = $false
[Terminal.Gui.Application]::RequestStop()
})
$btnCancel.add_Clicked({
[Terminal.Gui.Application]::RequestStop()
})
$btnShow.add_Clicked({
if ($txtPassword.Secret) {
$txtPassword.Secret = $False
$btnShow.Text = '_HidePwd'
}
else {
$txtPassword.Secret = $True
$btnShow.Text = '_ShowPwd'
}
})
#############ADD EVENTS TO WINDOW ITSELF#############
# handle closing window by pressing ESC (easier way)
[Terminal.Gui.Application]::QuitKey = 27
# add ability to close window via ENTER
[Terminal.Gui.Application]::Top.add_KeyPress({
param($e)
if ($e.KeyEvent.Key -eq [Terminal.Gui.Key]::Enter) {
$script:canceled = $false
[Terminal.Gui.Application]::RequestStop()
}
})
#############CONFIGURE UI#############
# insert default user name
$txtUserName.Text = "$env:userdomain\$env:username"
# set input focus to password box
$txtPassword.SetFocus()
#############SHOW UI##################
[Terminal.Gui.Application]::Run()
#endregion Sample TUI Window
# clean up
[Terminal.Gui.Application]::Shutdown()
###############CREATE RETURN VALUE######################
# if a user has cancelled the dialog, throw an exception
if ($canceled)
{
throw 'User cancelled login'
}
# else take the user input, create a credential, and return it
else
{
Try {
$SecureString = ConvertTo-SecureString -String $txtPassword.Text.ToString() -AsPlainText -Force
$credential = [PSCredential]::New($txtUserName.Text.ToString(), $SecureString)
return $credential
}
Catch {
Throw 'Failed to create a credential. Did you specify a username AND password?'
}
}
When you run this script, it opens a login dialog with the current username already filled in. The password box has focus, allowing the user to quickly enter the (masked) password and press ENTER, in whichcase the dialog returns a credential.
The user can also toggle between masked and clear text input.
As you can see from the code, TUI programming is quite similar to WinForms or WPF programming: each graphical element has a corresponding type. The user interface is composed in a tree structure where the window is the root, and other elements are added using Add().
The real magic begins when you start wiring events to these elements.
If you like what you see, you might want to use TUI not just in PowerShell 7, but also in Windows PowerShell. That’s exactly what we’ll tackle in the next part.
Your ultimate PowerShell Cheat Sheet
Unleash the full potential of PowerShell with our handy poster. Whether you're a beginner or a seasoned pro, this cheat sheet is designed to be your go-to resource for the most important and commonly used cmdlets. The poster is available for download and in paper form.
Related links
- ScriptRunners Script library provides ready-to-use PowerShell scripts.
- Try out ScriptRunner here
- ScriptRunner: Book a demo with our product experts