Channels ▼
RSS

.NET

Building GUI Applications in PowerShell


It might seem surprising to write an article on developing UIs with PowerShell, Microsoft's souped-up command-shell scripting language, but in reality, it makes a lot of sense. As developers, we need to deliver what the user wants, and that deliverable is sometimes a GUI. Being the lazy coder, I like to get my job done in the fewest lines of code possible. It's quicker, easier, less error-prone, and simpler to maintain if it can be coded in PowerShell. To run the examples I present below, you'll need ShowUI, the PowerShell module to help build WPF user interfaces in script.

Answer: Two Lines of Code

How many lines of PowerShell are needed to create a complete working WPF application? Two! Here's the code that yields the result shown in Figure 1.

Import-Module ShowUI
Label "Hello World" -FontSize 42 –Show


Figure 1: A simple display box.

It'll take you more time using statements, an IDE, and a compilation step to get the equivalent in C#. Here, you press Enter at the end of the second line of PowerShell code and you've got a running WPF app. I'll be going deeper into building PowerShell WPF applications in this article, but if you want another angle on using PowerShell to develop WPF applications, check out my MSDN article, "Secrets to Building a WPF Application in Windows PowerShell."

In this article, I show a couple of full WPF applications that make use of ShowUI: a Twitter search GUI and a video player. First, let's code up a GUI using WinForms.

PowerShell and WinForms

PowerShell works with WinForms out of the box. Figure 2 shows a simple WinForms GUI with a button. Click the button and the date will print in the console.


Figure 2: A simple WinForm built with PowerShell.

The PowerShell script for this WinForm (Listing One) has some code worthy of further explanation. First up, a PowerShell session does not automatically load the System.Windows.Forms DLL, so we use the Add- Type -AssemblyName System.Windows.Forms method to do so. If you use PowerShell and WinForms this way, there is no built-in editor to lay out your forms, so you need to manually handle position, sizing, and event hookup. (However, SAPIEN Technologies has a product called Primal Studio that contains a tool that works like the Visual Basic Forms Editor. It lets you drag and drop controls on a designer, hook up events by double-clicking the controls, and so on. The final result is all PowerShell. The tool, while commercial, can be tried at no cost.)

Listing One: Creating a simple WinForm in PowerShell.

Add-Type -AssemblyName System.Windows.Forms
$form = New-Object Windows.Forms.Form
$form.Size = New-Object Drawing.Size @(200,100)
$form.StartPosition = "CenterScreen"
$btn = New-Object System.Windows.Forms.Button
$btn.add_click({Get-Date|Out-Host})
$btn.Text = "Click here"
$form.Controls.Add($btn)
$drc = $form.ShowDialog()

After creating the form, I set its size and its start position. Then I create a Windows button, wire up the click event by calling the add_click() method, and pass it a PowerShell script block. I let the button's size take the default, and then I add the button to the form's Controls collection. Finally, the call to the ShowDialog() method displays the form on the screen.

Using WinForms to build GUIs has its advantages. It's available on any version of Windows, so you can e-mail a script to someone, and that person could run it and have a GUI ready to go.

Next up, I'll examine the the ShowUI module, which provides abstractions that cannot be achieved through pure markup.

Using ShowUI with the Twitter API

Being able to search social media sites quickly provides many benefits. In fact, there are companies that do this all day long, capturing details from Twitter and other social sites. After collecting all of this data, they run analytics to determine sentiment toward a product or service. While I won't get into specific analysis here, I'll show you how to query Twitter using its search API, process the XML results to easily work with the data in PowerShell, and then display it in a GUI. In less than a page of PowerShell script, I can glue together WPF and the results of a Twitter search!

When reading over this approach, keep in mind that this is not just for Twitter or social media sites with XML feeds. For example, you could use PowerShell v3 and change the search.rss to search.json. That returns a JSON string, and in PowerShell v3, you could pipe it to ConvertFrom-Json. Such a pipe would transform the data into PowerShell objects with properties that you could wire up into the ShowUI WPF application. Most sites on the Web today return either XML or JSON. They're just low-hanging fruit, waiting for a custom interface or a mashup.

The Search-Twitter function uses the search API and looks for the word "PowerShell." It accelerates the XML into an XmlDocument using [xml] and then dot-notates down to the item in the XML feed.

function Search-Twitter ($q = "PowerShell") {
   $wc = New-Object Net.Webclient
   $url = "http://search.twitter.com/search.rss?q=$q"
   ([xml]$wc.downloadstring($url)).rss.channel.item
}

Invoking the Search-Twitter function returns an array of objects, each with 32 properties on it. I'll select just two for now and look at the results.

Search-Twitter | select pubDate, title

The following data is what I get back from the search for the two selected fields:

pubDate                         title
-------                         -----
Fri, 10 Feb 2012 00:43:33 +0000 Windows PowerShell(TM) Scripting Guide
Fri, 10 Feb 2012 00:42:17 +0000 #PowerShell Use Tab Expansion in the Po
Fri, 10 Feb 2012 00:40:56 +0000 @energizedtech Captain! She canny take
Fri, 10 Feb 2012 00:37:56 +0000 Shout out to @ToddKlindt "the PowerShel
Fri, 10 Feb 2012 00:31:38 +0000 #PowerShell February PowerShell group m
Fri, 10 Feb 2012 00:29:57 +0000 RT @mattn_jp: powershell???????????????
Fri, 10 Feb 2012 00:22:32 +0000 @robinmalik: "Very excited to play arou
Fri, 10 Feb 2012 00:22:24 +0000 It seems like it is certainly going to
Fri, 10 Feb 2012 00:21:00 +0000 #PowerShell Using PowerShell v3 to cons
Fri, 10 Feb 2012 00:16:23 +0000 ????????···?????···PowerShell?????···??
Fri, 10 Feb 2012 00:16:16 +0000 Windows PowerShell v1.0: TFM, 2nd Editi
Fri, 10 Feb 2012 00:10:23 +0000 #PowerShell Windows PowerShell for Shar
Fri, 10 Feb 2012 00:08:55 +0000 Any #Powershell gurus out there that ca
Fri, 10 Feb 2012 00:08:51 +0000 ???: powershell?get-help???firefox?????
Fri, 10 Feb 2012 00:00:38 +0000 RT @ScriptingWife: R U ready for some #

This data might be useful, and so I save it to query later. But there are far more interesting fields in that data — the Twitter user's image, for example — so next let me make a little Twitter GUI app instead of just looking at raw data in this format.


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.
 

Comments:

ubm_techweb_disqus_sso_-7f1f00e1268e5ef28b5484400f7cba7b
2013-03-05T19:59:33

Re-Update: OK - my previous post works only for the Powershell session that creates the DLL. Once I close the powershell environment, and re-start it, nothing works, and I can't even re-issue Import-Module ShowUI -Force (which is how I generated the DLL the first time) unless I delete the \]Modules\ShowUI directory and unzip a "fresh" copy - then I can -Force, and it works again (until I close PS env again...then start over again, etc.) Our "user" directories (and thus our Windo3wsPowershell\Modules\ShoUI...) are on a network drive, and PS doesn't allow DLL to be loaded (apparently the -Force keeps the copy it creates in memory, so things work "1st time", and not thereafter) This post: http://labs.blogs.com/its_aliv... addresses this issue BUT apparently we have a group policy (or something) that precludes us from unblocking DLLs; Note that the Security option to UNBLOCK (as shown in the blog post) doesn't even appear on our file dialog. So I copied the \GeneratedAssemblies directory (contains DLLs and PDBs) to C:, and added to PATH - STILL no go, as ShowUI has "hardcoded" the user directory location in its accessors, So, final process (that "appears to work here" - and your mmileage will likely vary - is:
Download a copy of PowershellPack (nto sure if required, but one of the commments I read mentioned it, so what the heck...) and SHowUI. Install PowershellPack, and unzip ShhowUI to Modules as prescribed. --IFF-- your unzip made the Styles directory a sibling of StyleSystem, copy the Styles directory "inside" StyleSystems so it is now both a sibling (not sure if necessary, but it didn't hurt) --AND-- a descendant (which IS required). Note - if Winzip fouled me up, you may not need this step, as Styles may already be "inside" - mine was not for some reason. Then issue Import-Module ShowUI -Force to generate assemblies. After generated, -IFF_ your WindowsPowerShell directory is on a network drive, copy the \GeneratedAssemblies directory to a local drive. I also added to PATH, but this may not be necessary, as you need to then edit ShowUI.psm1 and change $psScriptRoot to C: in the following lines:

$CommandsPath = "C:\GeneratedAssemblies\ShowUI.CLR$($psVersionTable.clrVersion).dll"
$CoreOutputPath = "C:\GeneratedAssemblies\ShowUICore.CLR$($psVersionTable.clrVersion).dll"
(you will see $psScriptRoot in place of the "C:"s above)
and these lines:
Get-ChildItem C:\GeneratedAssemblies -Force -Recurse -Exclude $exclude -ErrorAction SilentlyContinue |
Remove-Item -Force -ErrorAction SilentlyContinue
Get-ChildItem C:\GeneratedCode -Recurse -Force -Exclude $exclude -ErrorAction SilentlyContinue |
Remove-Item -Force -ErrorAction SilentlyContinue
NOTE: -DO ---NOT--- "global change" the variable, as there are many references to .PS1 files that also use this variable...and we didn't move these scripts to C:...

NOW Import-Module ShowUI (without -Force) loads the DLLs and APPEARS to be working (more later, if I discover anything else...
HOPEFULLY, Mssrs Brundage, Finke, and/or Bennett will address these issues "officially" so that the above kludges are not required (AND potentially not even the total solution, or possible the cause of other issues, etc. - NO GUARANTEE PROVIDED-)


Permalink
ubm_techweb_disqus_sso_-7f1f00e1268e5ef28b5484400f7cba7b
2013-03-04T22:12:06

Follow-up: After unzipping ShowUI to Modules directory (again...), I looked and saw that a Styles directory was a sibling of StyleSystem directory instead of a descendant thereof. The error message stated that it was looking for .../StyleSystem/Styles/... which did not (exactly as the error message stated) exist....I copied Styles directory "inside" StyleSystem so that it is now a descendant AND a sibling, and the error message went away (I didn't MOVE - not sure that it is not needed as a sibling elsewhere, as I am not sure if WinZip fouled up unzipping, or if ShowUI -force was looking in the wrong place, or what...) BUT this seems to have resolved the issue (so far, anyway). I am using PS3 on Win7, and "small stuff" is working (haven't tried any colossal scripts yet...)


Permalink
ubm_techweb_disqus_sso_-7f1f00e1268e5ef28b5484400f7cba7b
2013-02-08T21:28:18

I also had this problem. As soon as I download and unzipped v1.3 from CodePlex, I immediately issued an "import-module showui -force" in the 32-bit ISE command window, as I saw James Brudage do in one of his vids. Result:->
PS C:\Users\sholton> import-module showui -force
Get-ChildItem : Cannot find path '\\itcfs014\HOME\WindowsPowerShell\Modules\showui\StyleSystem\Styles' because it does not exist.
At \\itcfs014\HOME\WindowsPowerShell\Modules\showui\StyleSystem\Import-UIStyle.ps1:33 char:33
+ foreach ($style in (Get-ChildItem -Force -Filter *.style -Path $psSc ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (\\itcfs014\HOME...leSystem\Styles:String) [Get-ChildItem], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand

Use-UiStyle : No Style named Current found
At \\itcfs014\HOME\WindowsPowerShell\Modules\showui\ShowUI.psm1:229 char:5
+ Use-UiStyle "Current"
+ ~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Import-UIStyle

PS C:\Users\sholton>

So the problem occurs "immediately" (actually not shown here is the "generating" thermometer, etc - the above command took a while and apparently generated a bunch of stuff - not sure what - and this is the end result).

If I then attempt to run the "show log" sample script (after adding import-module showui to the front of the provided sample), it works.

Haven't tried much else yet, and the initial "Styles" error didn't show up when I ran the show log script...hopefully, it won't rear its head again later...


Permalink
ubm_techweb_disqus_sso_-f5d6d7021e184edc39efcdbfe8b314c4
2012-12-06T22:52:00

Doug,

I have written a few apps with showui using powershell v2. However with powershell v3, I get the following error when trying to ipmo showui

PS C:\Users\bobr> Import-Module showui
Get-ChildItem : Cannot find path 'C:\Users\bobr\Documents\WindowsPowerShell\Modules\showui\StyleSystem\Styles' because
it does not exist.
At C:\Users\bobr\Documents\WindowsPowerShell\Modules\showui\StyleSystem\Import-UIStyle.ps1:33 char:33
+ foreach ($style in (Get-ChildItem -Force -Filter *.style -Path $psSc ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (C:\Users\bobr\D...leSystem\Styles:String) [Get-ChildItem], ItemNotFound
Exception
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand

Use-UiStyle : No Style named Current found
At C:\Users\bobr\Documents\WindowsPowerShell\Modules\showui\ShowUI.psm1:229 char:5
+ Use-UiStyle "Current"
+ ~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Import-UIStyle

Is showui known to work with powershell v3? It seems like the last version of showui was 1.3??


Permalink
ubm_techweb_disqus_sso_-6e41fcba8f47257080b3f0a2b1b3e9a5
2012-11-15T20:00:17

Sorry to hear you had all those issues.

ISE and the Command Line PowerShell are two different sessions. So, when you exited ISE, the ShowUI module was no longer available.

I have Import-Module ShowUI in both my console and ISE PowerShell $Profile.

Doug


Permalink
ubm_techweb_disqus_sso_-01e54ed7de40aaa09e991bc52bb5fa01
2012-11-14T02:14:39

With ShowUI you should use new-label not label. Obviously a small typo in the example.


Permalink
ubm_techweb_disqus_sso_-0e85e15d51296bf68bc7d3ab8a9cbd73
2012-11-10T23:31:43

I think it's time to give up on ShowUI! I haven't found a single sample other than Hello World that works, and now, after I exited the PowerShell ISE and restarted it, even that fails. 'Label "Hello World" -FontSize 42 –Show' is back to just executing the DOS lablel command. The promise of simple GUI's was temping, but I've wasted several days without managing to get any kind of foothold on what's required to do what. Time to move on....


Permalink
ubm_techweb_disqus_sso_-0e85e15d51296bf68bc7d3ab8a9cbd73
2012-11-10T00:30:04

Yes, I'd done that. Turned out that I was missing the PowerShellPack --- I finally found a comment somewhere that that was required. I knew something was missing, but when I searched for info on WPF I saw that it was part of .Net, and that led me astray. I'm still finding that most samples won't run, but I have made it past Hello World!


Permalink
ubm_techweb_disqus_sso_-6e41fcba8f47257080b3f0a2b1b3e9a5
2012-11-08T23:38:19

Did you do the first command? Import-Module ShowUI? Is the ShowUI module in the $env:PSModulePath?

Thanks
Doug
http://dougfinke.com


Permalink
ubm_techweb_disqus_sso_-0e85e15d51296bf68bc7d3ab8a9cbd73
2012-11-08T23:15:58

OK, I've spent most of two days now trying to get the Hello World sample to work! No luck! I'm running XP. I've got the PowerShell ISE up and running, and ShowUI installed, but PowerShell dosen't recognize New-Window, StackPanel, etc.
'Label "Hello World" -FontSize 42 –Show' does just what the normal label commnad does --- it 'labels' my C drive '"Hello World" -FontSize 42 –Show' .

What do I need? Where do I look?


Permalink

Video