I’ve created several PowerShell scripts that utilize Windows Presentation Foundation (WPF) for displaying a graphical user interface (GUI). The ability to use WPF GUIs enables you to combine PowerShell scripting and professional-looking GUIs – not like the old-school HTA GUIs in VBScripts.
WPF is completely being build on XML / XAML files – and these files can be build using the graphical forms designer in Visual Studio Community Edition:
The best of all is: Visual Studio Community Edition is free to download (https://www.visualstudio.com/en-us/downloads/visual-studio-2015-downloads-vs.aspx). All other versions of Visual Studio that will support WPF can also be used.
Let’s talk about the architecture of PowerShell and WPF GUI scripting. The first thing to understand is that the XAML file only contains the code for the GUI and no PowerShell Code at all.
<Window x:Class="WpfApplication1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525"> <Grid> <Button x:Name="button1" Content="Button" HorizontalAlignment="Left" Height="57" Margin="122,59,0,0" VerticalAlignment="Top" Width="241"/> <TextBox x:Name="textbox1" HorizontalAlignment="Left" Height="57" Margin="122,184,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="241"/> </Grid> </Window>
All functionalities, like clicking a button, etc. will be assigned in PowerShell to the corresponding controls. Once you’ve created your GUI you just need to copy the XAML file to your PowerShell script directory and you can start using the GUI.
# adding Microsoft .NET Framework types / classes Add-Type -AssemblyName PresentationFramework Add-Type -AssemblyName System.Windows.Forms function btnButton1_Click { $MainForm.FindName('textbox1').Text = "You pressed button1" } [XML]$XAML = Get-Content "MainWindow.xaml" $XAML.Window.RemoveAttribute("x:Class") $Reader = New-Object System.Xml.XmlNodeReader $XAML $MainForm = [Windows.Markup.XamlReader]::Load($Reader) # EVENT Handler $MainForm.FindName('button1').add_Click({ btnButton1_Click }) $MainForm.ShowDialog() | Out-Null
Important to understand is, that all events must be registered to the form before the GUI is being displayed. Events can be a buttonClick, Dropdown Menu, e.g. If you want to do some action when a button is being clicked you’ll need to create a function and add your function to the Event. In my example script, I registered the function btnButton1_Click on the event Click from the button1 control.
So the GUI knows what to do if someone clicks on button1 – it will automatically call my function btnButton1_Click.
Just wondering if you have a simple example of saving 2 or more separate windows in a single XAML file?
Hey Damir,
unfortunately not. Maybe you could use two XAML files, each for one window.
Thank You.
Really useful and to the point. I have spent some time to find this instruction and move away from win forms without putting xaml in source code.