Welcome to MSDN Blogs Sign in | Join | Help

WPF & PowerShell – Part 1 ( Hello World & Welcome to the Week of WPF )

Welcome to the Week of WPF.  During the next 7 days, I’ll help show you how you can use WPF and PowerShell together.

PowerShell could always script almost everything in .NET, but, prior to the recent CTP2 you could not script Windows Presentation Foundation (WPF) in PowerShell.

Now you can script everything that WPF can do within PowerShell.

This means you can write pretty sleek looking UIs in nice little PowerShell scripts.

There are a lot of things you can do with this capability, but let’s start things off simple.

 

Windows Presentation Foundation (WPF) is a set of .NET libraries for making next-generation user interfaces.  In order to script WPF classes, you have to start them in a Single Threaded Apartment (STA).  Luckily, starting in CTP2, you can run code in an STA a few ways in PowerShell.

 

In order to script WPF, you have to do one of three things:

·         Run the Script in Graphical PowerShell, where WPF scripts will run without any changes because Graphical PowerShell runspaces are STA.

·         Run the script in PowerShell.exe and add the –STA script

·         Create a background runspace that is STA, and run the script in the background runspace

 

In this post, I’ll show you a “Hello World” script, and how to run it in each of the three modes.

 

First, let’s write our “Hello World” script.   Open up Graphical PowerShell (gPowerShell.exe) and create a new script file (CTRL + N).

 

Here’s the Hello World file:

 

$window = New-Object Windows.Window

$window.Title = $window.Content = “Hello World.  Check out PowerShell and WPF Together.”

$window.SizeToContent = “WidthAndHeight”

$null = $window.ShowDialog()

 

Now in Graphical PowerShell, you should be able to just run it and be done.

 

You can run the current script in Graphical PowerShell with F5 or the Green Run button in the upper left of the editor.

 

Now let’s run the script in STA Mode PowerShell (Run PowerShell –sta).  Save it as “HelloWorld.ps1”

 

Since PowerShell.exe –sta doesn’t load up WPF’s assemblies, lets run these three lines to add the references:

 

Add-Type –assemblyName PresentationFramework

Add-Type –assemblyName PresentationCore

Add-Type –assemblyName WindowsBase

.\HelloWorld.ps1

 

Now you have a Hello World in WPF from the console version of PowerShell.

 

Finally, you can embed scripts to generate WPF inside of an application or a background runspace.  This has some advantages over the first two approaches… namely, without a background

 

The code below will create a background runspace and set the two properties required to make WPF work in a PowerShell runspace, ApartmentState and ThreadOptions.  ApartmentState determines if the runspace PowerShell is single or multithreaded (WPF requires single threaded), and if the same thread is used every time a command is run, or if a new thread is created each time.  For WPF scripting to work in a runspace, you have to set ApartmentState to “STA” and ThreadOptions to “ReuseThread”.  In the code below, the first 3 lines set up the runspace, the next 10 lines ensure that runspace is able to load WPF classes, and the final 4 lines run our original HelloWorld.ps1

 

# Create a runspace to run Hello World

$rs = [Management.Automation.Runspaces.RunspaceFactory]::CreateRunspace()

$rs.ApartmentState, $rs.ThreadOptions = “STA”, “ReuseThread”

$rs.Open()

# Reference the WPF assemblies

$psCmd = {Add-Type}.GetPowerShell()

$psCmd.SetRunspace($rs)

$psCmd.AddParameter("AssemblyName", "PresentationCore").Invoke()

$psCmd.Command.Clear()

$psCmd = $psCmd.AddCommand("Add-Type")

$psCmd.AddParameter("AssemblyName", "PresentationFramework").Invoke()

$psCmd.Command.Clear()

$psCmd = $psCmd.AddCommand("Add-Type")

$psCmd.AddParameter("AssemblyName", "WindowsBase").Invoke()

$sb = $executionContext.InvokeCommand.NewScriptBlock(

(Join-Path $pwd "HelloWorld.ps1")

)

$psCmd = $sb.GetPowerShell()

$psCmd.SetRunspace($rs)

$null = $psCmd.BeginInvoke()

 

This is just a taste of some of the fun that PowerShell and WPF can have together, and how to get it working.  You can now use everything in WPF in a PowerShell script.

 

During the Week of WPF, I will post one script each day that will take us a little further down the rabbit hole of what PowerShell and WPF can do together.  After the week of WPF is done, keep your eyes on this space, because every Wednesday, I’ll try to post a “WPF Wednesday Widget” that uses showcase using PowerShell and WPF together.

 

Hope this Helps,

James Brundage [MSFT]

Published Thursday, May 22, 2008 7:16 AM by PowerShellTeam

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

# re: WPF & PowerShell – Part 1 ( Hello World & Welcome to the Week of WPF )

Hi James,

interesting post, it's good to see PowerShell expanding in features and capabilities.  

It's also a good example of why I find PowerShell pretty annoying.  You've given three completely different ways of doing something, two of which aren't in the least bit intuitive and the easiest of them doesn't work.  

When I paste the example above into gPowerShell and hit F5 it fails, with the error "the calling thread must be STA, because many UI components require this".  No doubt I've omitted some 'obvious' step such as manually setting my default gPowerShell Thursday execution policy to be green.

I'm not even going to bother with the other two methods as no doubt some other mysterious setting needs to be changed from it's default for these to work properly.

This is just a general example of why I find PowerShell absolutely exasperating.  There seem to be many, many ways of doing the same task, most of which have some undocumented 'miracle happens here' step completely unrelated to the task at hand.  ("You want to display a window?  Make sure you change the environment threading model first!" WTF??) How are we supposed to establish best practice and create re-usable code with such a profusion of approaches and convoluted mechanisms of making them run?

Another bug-bear is ADSI, which I spend quite a bit of my time (normally) coding with VBScript.  I've tried to convert to PowerShell but good grief it's an irritating experience.  

Yesterday, for example, I spent ages wrestling with a bit of pipeline code to show a table of people who had non-default mailbox size limits.  Doing the search went fine, and using (an entirely non-obvious) bit of code from the internet I got it into a table.  

I then wanted to show the output in MB instead so did a ' / 1MB'; did it work?  "no division operator for property result set".  So, convert it a string then do it (as there's no toInt() function I take a guess it might implicitly convert a string, like it would in VBScript).  Still doesn't work, "no division operator for string".  Cast it to an int, still doesn't work, it tries to cast the propertyresult to an int before running the .toString(), not after,  and fails "can't convert propertyresult to int".  Try putting brackets round the blah.ToString(), to force it to run first.  Fails.  Give up.  Resort to copying it out from the screen and pasting it into Excel and converting it there.  Rubbish.  

Rant over, and apologies for straying way off topic here (and directing this rant at you). I do appreciate all the effort the PowerShell guys are making to evangelise and give examples of PowerShell at work.  I'm just finding it too hard to translate the stuff I do into the PowerShell way; the balance between "effort required to make it work" versus "benefits of migrating from VBScript" to my mind isn't tipped in the right direction.

Thursday, May 22, 2008 7:21 AM by Andrew Macaroon

# Dew Drop - May 22, 2008 | Alvin Ashcraft's Morning Dew

Thursday, May 22, 2008 10:27 AM by Dew Drop - May 22, 2008 | Alvin Ashcraft's Morning Dew

# re: WPF & PowerShell – Part 1 ( Hello World & Welcome to the Week of WPF )

Aren't these precisely the low-level details that are supposed to be encapsulated within cmdlets?  This isn't that much easier than just doing it in C#.  I agree that it's cool to be able to do it, and I liked the article and will certainly read the rest in the series, but I doubt any of this will help to spread adoption of PowerShell among those new to it, and might even turn some of them off.  I wish Microsoft would spend more time fixing known bugs than packing in new features that will be very rarely used.  How about allowing PowerShell scripts to be directly pushed out through Group Policy without a VBScript wrapper?  Or adding Active Directory cmdlets that work?  Or supporting long file paths?  Or making the SQL cmdlets better?  Or adding support for VBScript's GetObject() method?  Or getting PowerShell to work on Server Core?  Or making powershell.exe launch as quickly as cmd.exe?

Thursday, May 22, 2008 11:06 AM by Pepper Pots

# @Andrew Macaroon

Andrew,

Please detail your problems, then we can help you, and maybe help others who come along with the same issue.

As an MVP, we tend to not always be in touch with the troubles newcomers can face, as things have changed even as of 12 months ago.

As for the STA/gPowerShell problem...  You are running v2 CTP2 right?  v2 CTP1's gPowerShell doesn't support STA mode.

Thursday, May 22, 2008 12:52 PM by Marco Shaw

# @ Anderw Macaroon (part 2)

Andrew,

As for the "having multiple ways to do the same thing"...

All the methods are quite different and serve their own purpose.

For a typicaly admin, the command-line method would likely be choice #1.  #2 can be used to actually test/develop the script by an admin, before ones copies it into a script to be run by powershell.exe.

Option #3 is more geared for developers who could be using PowerShell *inside* their applications.

Thursday, May 22, 2008 1:01 PM by Marco Shaw

# More PoSHy WPF from PowerShell coverage

Now also James Brundage from the PowerShell team started a series on WPF from PowerShell, Starting with

Thursday, May 22, 2008 1:12 PM by The PowerShell Guy

# re: WPF & PowerShell – Part 1 ( Hello World & Welcome to the Week of WPF )

I like this - look forward to the other articles.

Shouldn't the New-Runspace (and other runspace) cmdlets be expanded to cover the use of a runspace in your third example

Thursday, May 22, 2008 2:53 PM by Richard Siddaway

# Windows Presentation Foundation & PowerShell

Hard Hat Area: Programmers.... Server 2008 tidbit.... PowerShell...create some real nice user interfaces

Thursday, May 22, 2008 5:27 PM by The Medical Quack .... by Barbara Duck

# re: WPF & PowerShell – Part 1 ( Hello World & Welcome to the Week of WPF )

Ugh, I could make a peanut butter and squid sandwich, but that doesn't mean you should.

Thursday, May 22, 2008 6:30 PM by caywen

# re: WPF & PowerShell – Part 1 ( Hello World & Welcome to the Week of WPF )

Interesting post but we have a simple question... how can we do to run a powershell script that shows for example a form with some controls but without the black console window in the background? how can we hide the black console window? Is it possible?

Friday, May 23, 2008 5:28 AM by Pablo

# @ Richard Siddaway

Richard,

new-runspace/start-psjob only support the MTA threading model/state.

So, one can't use these and have WPF behave correctly in all circumstances.

Friday, May 23, 2008 9:25 AM by Marco Shaw

# re: WPF & PowerShell – Part 1 ( Hello World & Welcome to the Week of WPF )

This is only meant to be MILDLY snarky.

Thanks, just what I need, seven days of examples of how to use BETA code.  I live in a production world.  When will the new version ship?

Friday, May 23, 2008 10:25 AM by Dan

# re: WPF & PowerShell – Part 1 ( Hello World & Welcome to the Week of WPF )

> This is only meant to be MILDLY snarky.

"Snarky" - what a GREAT word.  I just love that word.

> Thanks, just what I need, seven days of examples of how to use BETA code.  I live in a production world.  When will the new version ship?

It's worse than that my friend.  This is not BETA code, its CTP code.  That's a LONG way away from Beta.  V2 is a huge (compatible) release with lots of new features and we need to promulgate those features to our early adopters so they can kick the tires and tell us if we got it right, almost right, or our heads are in the wrong place of our anatomy.

YOU benefit from this because at some point we'll ship these features and the feedback from our early adopters hopefully acts as a proxy for your needs and you get what you want without having to take the production code, file a bunch of bugs/feature requests and wait a couple of years to get them addressed.  

Of course if these early adopters don't reflect your needs, you're screwed.  You might want to think about that when deciding whether to blow of the CTP or not.  

This blog is going to have a content for both existing and new stuff but is probably going to lean towards the newer stuff because we want people to use it and give us feedback.  That might mean that our signal-to-noise ratio is wrong for you until we ship V2.  That's fine - no harm/no foul - we'll enjoy your company when you join us again.

So - when will the new version ship?  Here is the deal:  We were only given permission to have a CTP if we promised never to answer that question.  That said, here is what I can say.  We are coding new features for a couple more weeks and then it has typically taken us a year plus or minus a quarter to bake the release to the point that customers tell us it is ready to ship.

Jeffrey Snover [MSFT]

Windows Management Partner Architect

Visit the Windows PowerShell Team blog at:    http://blogs.msdn.com/PowerShell

Visit the Windows PowerShell ScriptCenter at:  http://www.microsoft.com/technet/scriptcenter/hubs/msh.mspx

Friday, May 23, 2008 11:42 AM by PowerShellTeam

# re: WPF & PowerShell – Part 1 ( Hello World & Welcome to the Week of WPF )

Jeffrey,

Thanks.  I really appreciate your answer.  And I really appreciate PS.  I had been doing most of my work in Perl and I am very happy to move to this new tool.  I see PS as being a seriously big deal for me, I just can't get involved in development code right now.

Thanks again.

Friday, May 23, 2008 11:57 AM by Dan

# @ Pablo

Pablo,

You want to get rid of the PowerShell console?  Can you be more specific?

Friday, May 23, 2008 2:07 PM by Marco Shaw

# re: WPF & PowerShell – Part 1 ( Hello World & Welcome to the Week of WPF )

The questions is that I can't execute a powershell script without the black console window. For example when I run a vbs script, we only need to run the command: wscript.exe example.vbs and this command do not open a cmd console :-)

Another example. Look my example.ps1 script:

[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")

[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")

$objForm = New-Object System.Windows.Forms.Form

$objForm.Text = "Example"

$objForm.Size = New-Object System.Drawing.Size(100,100)

$objForm.StartPosition = "CenterScreen"

$objForm.Add_Shown({$objForm.Activate()})

[void] $objForm.ShowDialog()

when I run this script: powershell.exe .\example.ps1 the windows form appears correctly but I can´t hide the powershell console. How can I do?

Friday, May 23, 2008 5:26 PM by Pablo

# @ Pablo

Pablo,

Ah yes, the annoying black widow... ;-)

I've tried posting URLs in the comments before and they seem to always be rejected.  I'd go to the microsoft.public.windows.powershell newsgroup and ask...

Sunday, May 25, 2008 8:54 PM by Marco Shaw

# re: WPF & PowerShell – Part 1 ( Hello World & Welcome to the Week of WPF )

I'll include this in a later post in the series, but I'll post it here for Pablo.  You can Minimize /Maximize Powershell by calling Win32 Functions through C interop:

$showWindowAsync = Add-Type –memberDefintion @”

[DllImport("user32.dll")]

public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);

“@ -name “Win32ShowWindowAsync” -namespace Win32Functions –passThru

# Minimize PowerShell

$showWindowAsync::ShowWindowAsync((Get-Process –id $pid).MainWindowHandle, 2)

sleep 2

# Then Restore it

$showWindowAsync::ShowWindowAsync((Get-Process –id $pid).MainWindowHandle, 4)

Hope this Helps,

James Brundage[MSFT]

Sunday, May 25, 2008 9:44 PM by PowerShellTeam

# re: WPF & PowerShell – Part 1 ( Hello World & Welcome to the Week of WPF )

Great! It is what I surely hoped.

But I hope -Minimize and -NoWindow start options for powershell.exe, too.

Are they shipping on next milestone? Or will ship?

Monday, May 26, 2008 1:25 AM by Smith Catar

# re: WPF & PowerShell – Part 1 ( Hello World & Welcome to the Week of WPF )

@PowerShellTeam

Thanks. Interesting workaround :-) I'll try it. It will be very interesting for IT Administrators that we can hide the console completely (if the black window is minimized the final user can close it). Thanks again for the help.

Monday, May 26, 2008 7:48 AM by Pablo

# Visual Studio Links #32

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

Tuesday, May 27, 2008 7:57 AM by Visual Studio Hacks

# re: WPF & PowerShell – Part 1 ( Hello World & Welcome to the Week of WPF )

I`ve just tried your code on PS V2 CTP Graphical and I`ve received an exception:

Exception calling ".ctor" with "0" argument(s): "The calling thread must be STA, because many UI components require this"

So probably there is something to tune in runspace.

The only change I`ve made to standard PS Runspace is

Set-ExecutionPolicy RemoteSigned

Regards,

Gianluca

Wednesday, May 28, 2008 5:35 AM by Gianluca

# @ Gianluca

Gianluca,

You must be running the v2 CTP2 gPowerShell.  A v2 CTP was release also, but it doesn't support STA.  I'm assuming the problem is that you're running an old CTP version.

Wednesday, May 28, 2008 1:23 PM by Marco Shaw

# @Marco

You are right!

I`ve missed the CTP2 release announce, sorry.

Just downloaded, thanks.

Thursday, May 29, 2008 8:57 AM by Gianluca

# Shame on most of us out there

Lee and Suzanne here makes a good point. Shame on all of us for not at least acknowledging that this

Saturday, February 07, 2009 12:08 AM by It's my life... And I live it...

# re: WPF & PowerShell – Part 1 ( Hello World & Welcome to the Week of WPF )

Hi all,

I installed the latest PS-version for XP, SP3. When I run the example code, I also get a...

"

Exception calling ".ctor" with "0" argument(s): "The calling thread must be STA, because many UI components require this"

"

What's wrong? -A version dump shows this:

> $PSVersionTable

Name                           Value

----                           -----

CLRVersion                     2.0.50727.3603

BuildVersion                   6.0.6002.18111

PSVersion                      2.0

WSManStackVersion              2.0

PSCompatibleVersions           {1.0, 2.0}

SerializationVersion           1.1.0.1

PSRemotingProtocolVersion      2.1

TNX!

Monday, February 01, 2010 4:41 AM by Heiko

Leave a Comment

(required) 
required 
(required) 

  
Enter Code Here: Required
 
Page view tracker