WPF & PowerShell – Part 2 (Exploring WPF (and the rest of .NET) with Scripts)

WPF & PowerShell – Part 2 (Exploring WPF (and the rest of .NET) with Scripts)

  • Comments 6

In my previous post, I showed you how to create “Hello World” scripts using Windows Presentation Foundation (WPF) and Windows PowerShell.

While “Hello World” is relatively easy to write with WPF, it is only the tip of the iceberg of the types of quick user interfaces you can write.

Windows Presentation Foundation provides an amazing array of controls for an incredible array of purposes.  Out of the box, with just one control, you can:

·         Show a listbox

·         Play a video or audio file

·         Capture user drawings

·         Display an image

·         Draw a complex polygon

·         Display a slider


All controls can use video, images, gradients, and rich colors as their background or foreground.  All controls can interact with Tablet PC input, Keyboard, and Mouse.  All windows can be transparent.


In the vastness of WPF, there is not a Get-Command or a Get-Help to help you discover what you can do with WPF.  The existence of Get-Command and Get-Help is one of my favorite things about PowerShell, because it helps close what I call the Discoverability Gap.   The Discoverability Gap is the difficulty in a scripter of developer determining what solutions exist for a problem.


While PowerShell has an elegant solution to the Discoverability Gap, there have been many good attempts in the past.  .NET’s is refection.  In this post I’ll give you a couple of functions that help close the Discoverability Gap for .NET, and then show you how to find examples on MSDN.


You’ll need three functions for the fun.  They’re all one liners.


# Looks returns all of the .NET types currently loaded by PowerShell

function Get-Type() { [AppDomain]::CurrentDomain.GetAssemblies() | % { $_.GetTypes() }}


# Opens a webpage to connect to look up information about the Type on MSDN (e.g http://msdn.microsoft.com/en/library/System.Windows.Window.aspx )


function Get-MSDNInfo([Type]$t) { (New-Object –com Shell.Application).Open(“http://msdn.microsoft.com/$(Get-Culture)/library/$($t.FullName).aspx” ) }


# Create a new instance of an object and displays member info with Out-GridView, so you can search the information to find a property that might do what you want

function Show-ClassInfo([Type]$t) { Get-Member –input (New-Object $t.FullName $args) | Out-Gridview}


With these commands, I can close a of the discoverability gap for WFP & all of .NET, much more quickly.


Now let's walk through how we use these commands to find out what else is in WPF, and show some more quick WPF & PowerShell samples.


WPF is in the System.Windows namespace and subnamespaces, and all controls are inherited from [Windows.Controls.Control], so you can quickly find all of the loaded controls with this one liner:


Get-Type | Where-Object { $_.IsSubclassOf([Windows.Controls.Control])}


First, let’s find a label, so we can change the font size of the Hello World.


Get-Type | Where-Object { $_.IsSubclassOf([Windows.Controls.Control])} | Where-Object {$_.Name –eq “Label”} | Select FullName






Now, let’s go open it in MSDN and create a gridview containing a label:


Get-MSDNInfo System.Windows.Controls.Label

Show-ClassInfo System.Windows.Controls.Label


The MSDN page gives you the details on everything that is just applicable to the label, but Get-Member gives you every property, method, and event the control has.


A quick scrolling down this list will give you an idea of just how big the iceberg is. The label alone has 246 methods, properties, and events.


Luckily for us, Out-Gridview has a search window.  Let’s use it to find the properties named Size.




An Event, SizeChanged

A method, Measure, which takes a Size type

A DesiredSize Property

A FontSize Property

A RenderSize Property


Obviously, FontSize is the one we want to use to make our Hello World a little larger and easier to read.


Now our HelloWorld is:


$window = New-Object Windows.Window

$window.Title = “Hello World”

$label = New-Object Windows.Controls.Label

$label.Content, $label.FontSize = “Hello World”, 24

$window.Content = $label

$window.SizeToContent = “WidthAndHeight”

$null = $window.ShowDialog()


Let’s take a quick tour of some of the other really simple things we can do with WPF:


Create a Circle of a Random Size:


$window = New-Object Windows.Window

$color = (“Red”, “Green”,”Blue”,”Yellow” | Get-Random)

$window.Title = “See The Big $color Ball”

$circle = New-Object Windows.Shapes.Ellipse

      $circle.Width = $circle.Height = Get-Random –min 200 –max 450

      $circle.Fill = $color

      $window.Content = $circle

      $window.SizeToContent = “WidthAndHeight”

      $null = $window.ShowDialog()


Create an Ink Canvas the user can scribble on with the mouse or stylus


     $window = New-Object Windows.Window

     $window.Title = “Scribble on Me”

     $inkCanvas = New-Object Windows.Controls.InkCanvas

     $inkCanvas.MinWidth = $inkCanvas.MinHeight = 100

     $window.Content = $inkCanvas

     $window.SizeToContent = “WidthAndHeight”

     $null = $window.ShowDialog()


Show a slider, and get the value the slider was at after running:


$window = new-object Windows.Window

$slider = New-Object Windows.Controls.Slider

$slider.Maximum = 10

$slider.Minimum = 0

$window.Content = $slider

$window.SizeToContent = "WidthAndHeight"

$null = $window.ShowDialog()



Show a label and textbox, and emit the value the textbox contained:


$window = new-object Windows.Window

$stackPanel = new-object Windows.Controls.StackPanel

$text = New-Object Windows.Controls.TextBox

$label = New-Object Windows.Controls.Label

$label.Content = "Type Something"



      $window.Content = $stackPanel

$window.SizeToContent = "WidthAndHeight"

$null = $window.ShowDialog()



This post should give you a better sample of what WPF Contains, and how to close the Discoverability Gap and learn how to script more.  Stay tuned to see more interactive WPF.


Hope this Helps,

James Brundage [MSFT]

Leave a Comment
  • Please add 5 and 2 and type the answer here:
  • Post
  • As an alternative to creating a COM object to open the URL, I use this function to create a .url file and then pass that to Invoke-Item cmdlet.  

    New-UrlFile code listing: http://powershellcentral.com/scripts/407

  • I love your series so far! In fact, I loved it so much I added a -STA switch to PowerShell Plus. So now you can use PS+ with full intellisense and debugging for WPF scripts as well. -STA support was introduced in version which you can get here if you like: www.powershell.com/downloads/psp1new.zip.

    This version is not yet made public except for the link above. Enjoy!

  • My latest in a series of the weekly, or more often, summary of interesting links I come across related to Visual Studio. JetBrains has announced the release of the ReSharper 4.0 Beta . Hilton Giesenow has created a video titled How Do I: Add A Dialog

  • There's a simple yet powerful function that nearly everyone on the PowerShell team has written a version

  • Your examples are wonderful!

  • Hi, This tutorial was my base knowledge when making powershell + wpf application, thanks for this post it gives me a place to start learning it. Right now I am in the middle of creating an application (ps + wpf). I wanna turn my form into Metro theme style which i did when i was using singe xaml page. But how to do it when using resource dictionary? (External xaml source file) Here is my code:

    #build the GUI


    cd "D:\powershell\Lesson\metro"

    Add-Type –assemblyName PresentationFramework

    Add-Type –assemblyName PresentationCore

    Add-Type –assemblyName WindowsBase

    [xml]$xaml = @"




       WindowStartupLocation="CenterScreen" Name="MainFrm"

       Width="800" Height="700" ShowInTaskbar="True">




                           <ResourceDictionary Source="Metro.MSControls.Core.Implicit.xaml" />

                           <ResourceDictionary Source="Metro.MSControls.SDK.Implicit.xaml" />

                           <ResourceDictionary Source="Metro.MSControls.Toolkit.Implicit.xaml" />






    $reader = (New-Object System.Xml.XmlNodeReader $xaml)

    $Window = [Windows.Markup.XamlReader]::Load($reader)


    ******i hope someone will email me Lumus_maxima@rocketmail.com

Page 1 of 1 (6 items)