PowerShell has full access to the .NET Framework and can therefore utilize all the graphical functions available in .NET. However, even though .NET Core is cross-platform, all graphical APIs are currently limited to the Windows operating system. If you choose this approach, your script will be restricted to Windows.

In the previous tip, we explored the older Windows Forms technique for creating a simple user interface. Today, we'll do the same using the newer WPF (Windows Presentation Foundation).

Generating UIs with WPF typically follows these steps:

  1. Load the required .NET assemblies
  2. Create a blank window (System.Windows.Window)
  3. Create a grid control with rows and columns to position UI elements
  4. Create the required UI elements and place them in grid cells
  5. Show the window
  6. Evaluate the user input after the window has been closed

To illustrate these steps, here is a simple WPF-based UI that prompts the user to enter a username for logon:


# load the required .NET assemblies (requires Windows operating system)
Add-Type -AssemblyName PresentationCore
Add-Type -AssemblyName PresentationFramework


# define content of user interface
$WindowTitle = 'Enter User Name'
$OkText = 'Log On'
$CancelText = 'Abort'
$Prompt = 'Please enter user name:'
$DefaultValue = $env:USERDOMAIN + '\' + $env:USERNAME

# create blank window
$form = [System.Windows.Window]::new()
$form.Title = $WindowTitle
$form.SizeToContent = [System.Windows.SizeToContent]::WidthAndHeight
$form.WindowStartupLocation = [System.Windows.WindowStartupLocation]::CenterScreen


# use a grid to position elements
$grid = [System.Windows.Controls.Grid]::new()
# use a uniform 10 units margin:
$grid.Margin = 10

# Define rows
$row1 = [System.Windows.Controls.RowDefinition]::new()
$row2 = [System.Windows.Controls.RowDefinition]::new()
$grid.RowDefinitions.Add($row1)
$grid.RowDefinitions.Add($row2)

# Define columns
$col1 = [System.Windows.Controls.ColumnDefinition]::new()
$col2 = [System.Windows.Controls.ColumnDefinition]::new()
$grid.ColumnDefinitions.Add($col1)
$grid.ColumnDefinitions.Add($col2)

# create OK button
$OKButton = [System.Windows.Controls.Button]::new()
$OKButton.Width = 100
$OKButton.Content = $OkText
# this is the official OK button and can be operated via ENTER:
$OKButton.add_click({ $form.DialogResult = $true })

# place button in grid cell 1/1
[System.Windows.Controls.Grid]::SetRow($OKButton, 1)
[System.Windows.Controls.Grid]::SetColumn($OKButton, 1)
$null = $grid.Children.Add($OKButton)

# create CANCEL button
$CancelButton = [System.Windows.Controls.Button]::new()
$CancelButton.Width = 100
$CancelButton.Content = $CancelText
# this is the official cancel button and can be operated via ESC:
$CancelButton.IsCancel = $true
# place button in grid cell 1/0
[System.Windows.Controls.Grid]::SetRow($CancelButton, 1)
[System.Windows.Controls.Grid]::SetColumn($CancelButton, 0)
$null = $grid.Children.Add($CancelButton)

# create a label
$label = [System.Windows.Controls.Label]::new()
$label.Content = $Prompt
# place label in grid cell 0/0
[System.Windows.Controls.Grid]::SetRow($label, 0)
[System.Windows.Controls.Grid]::SetColumn($label, 0)
$null = $grid.Children.Add($label)

# create textbox to enter a text
$textBox = [System.Windows.Controls.TextBox]::new()
$textBox.Text = $DefaultValue
# use a small margin
$textBox.Margin = 5
# place textbox in grid cell 0/1
[System.Windows.Controls.Grid]::SetRow($textBox, 0)
[System.Windows.Controls.Grid]::SetColumn($textBox, 1)
$null = $grid.Children.Add($textBox)


# add grid to window
$form.Content = $grid

# make it top-most
$form.Topmost = $true

# when the form shows, select the textbox
$null = $textBox.Focus()

# show dialog in a modal dialog window
$result = $form.ShowDialog()
$hasCanceled = $result -ne $true

if ($hasCanceled)
{
 throw 'User canceled dialog'
}

# read textbox content
$textBox.Text

The most fundamental difference in this WPF code—compared to Windows Forms—is that it doesn’t position elements using pixel values. Instead, it places them within a flexible grid, where all physical sizes and positions are calculated dynamically—including the size of the dialog window itself.

This is why WPF windows always scale correctly, even on high-definition displays, and can be resized: the UI elements inside reposition themselves automatically.

In conclusion, WPF-based user interfaces can be programmed similarly to Windows Forms but offer much better scaling—especially on high-definition displays. However, they still require the Windows operating system.

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.

Get your poster here!

Related links