Building GUI Forms with PowerShell
Not every tool is a console command. System.Windows.Forms turns a script into a window with labels, text boxes and buttons — a small app your team can click instead of learning your parameters.
Documentation: Windows Forms documentation
What Windows Forms does
Windows Forms is the .NET way to build desktop windows, and PowerShell can drive it directly because PowerShell is .NET. Load the assembly, create a Form object, add controls to it, and display it. The script pauses at ShowDialog until the user closes the window, then continues with whatever the user entered.
A form is just objects: a Form with a Text title and a Size, Labels that display text, TextBoxes that collect input, Buttons that run code when clicked. Each control has a Location and a Size, measured in pixels from the form's top-left corner.
Two limits matter. Forms are Windows-only — the same script cannot show a window on macOS or Linux. And PowerShell 7 runs in multi-threaded apartment mode by default while Forms requires single-threaded apartment mode, so a Forms script in PowerShell 7 must be launched with pwsh -STA. Windows PowerShell 5.1 is STA by default and needs no flag.
See the objects move
Inspect this authored example with fictional data in the bounded browser model. The numbered stages show how its objects change.
Add-Type -AssemblyName System.Windows.Forms- Stage 1Add-Type -AssemblyName System.Windows.Forms
Try it: a two-control form
Build a form
Load the assembly, create the form, add a label, a text box and a button, then wire the button's click event:
Add_Click takes a script block that runs when the button is pressed. Inside it, $box.Text reads what the user typed. MessageBox shows the result. ShowDialog displays the form and waits; Dispose releases it afterwards.
Layout is manual: every control needs a Location and usually a Size. For larger tools, set the form's StartPosition to CenterScreen, anchor controls so they resize with the window, and keep the click handlers short — long work inside a click freezes the window until it finishes.
Try it: a two-control form
The smallest useful form: one label, one button, one message. Paste it into a console and watch a window appear:
Click the button and a message box appears. Close the message box, then close the form — the console prompt returns only after the form closes, because ShowDialog blocks until then.
Common mistakes
- Forgetting ShowDialog. A form that is built but never shown does nothing. The script ends and the window never appears.
- Running Forms in PowerShell 7 without -STA. The form may fail or behave strangely. Launch with pwsh -STA, or run the script from Windows PowerShell 5.1.
- Expecting it on macOS or Linux. System.Windows.Forms is Windows-only. The same script throws on other platforms.
- Long work inside a click handler. The window freezes while the handler runs. Keep clicks short, or run heavy work as a job and update the form when it completes.
- Skipping Dispose. Without it, window handles linger. Always Dispose the form after ShowDialog returns.
Your turn
On your own machine, extend the greeting form: add a second text box for a department, and make the button's message include both the name and the department. Then add a second button labeled Clear that empties both boxes.
Prove it: write it alone
Blank editor. No starter, no hints. Write a script that shows a form with a text box and a button, where clicking the button displays the typed text in a message box — then closes cleanly.
Practise this
Build a greeting form
Build a form with a text box and a button that greets the name typed into it.
The sandbox is visible now. Sign in with Google only when you run or check a task; commands and temporary files are discarded when you leave.
Run a command to inspect its result.
Inspect starting data
Supported syntax
Virtual files
Recap
Windows Forms turns a script into a clickable window: load the assembly, build a Form, add controls with locations and sizes, wire events with Add_Click, and show it with ShowDialog. It is Windows-only, needs -STA in PowerShell 7, and for richer layouts the next step is WPF with XAML — same idea, declarative layout instead of pixel positions.