The topic: Extending PowerShell to the GUI with ShowUI. ShowUI is a PowerShell module to help build WPF user interfaces in script. ShowUI makes the complicated world of WPF easy to use in PowerShell.
I will be demoing How To
Build a standalone PowerShell ShowUI WPF application
Run this app in the background
Get data asynchronously
Use variable splatting to enable the app as a custom control
Use the same app standalone, in the background and embedded in another ShowUI WPF app
The common controls we currently deliver with ShowUI out of the box
It’s going to be fun, informational talk. Looking forward to it.
ThoughtWorks is "A social and commercial community whose purpose is to revolutionize software creation and delivery while advocating for positive social change in the world."
The Tech Radar places PowerShell in the “Trial” quadrant but I suspect that to quickly move to the “Adopt” quadrant after the Microsoft BUILD Conference when the new features of Windows 8 is announced.
In this post I’ll use ShowUI and port Sean’s example. The challenge, ShowUI is a PowerShell Module that needs to be xCopy deployed to the users machine so I can create these WPF GUI applications.
ShowUI
ShowUI is a PowerShell module to help build WPF user interfaces in script. ShowUI makes the complicated world of WPF easy to use in PowerShell.
Sean steps through creating a simple GUI for capturing a user’s first and last name so it can be used with PowerGUI’sGet-QADUser cmdlet. First up, is a simple form with an ‘UNLOCK Account’ button.
Button"Unlock Account"-Show-Margin10-On_Loaded{$Window.Title="Our Help Desk"}
Now, Capture the User Information
I’ll wrap the ShowUI code in a function Get-UserInfo. I like this practice because it makes the GUI widget reusable. In an upcoming post I’ll drill down on how to create custom controls. For now I will reproduce Sean’s user info screen.
I use a WPF Grid which lets me lay out controls in Rows and Columns. I use 3 rows, one row for the labels, one for the text boxes and the last for the button. Every control in ShowUI supports a Row and Column parameter, so they can all be laid out this way.
I write fewer lines of code using a WPF grid container. For example, when I resize the window all the controls resize automatically. Give it a try.
Next up, I show the magic to returning the data entered on the form as PowerShell Hashtable.
functionGet-UserInfo{Grid-Rows3-Columns2-Show-On_Loaded{$Window.Title="Our Help Desk"}{Label"First Name"-Row0-Column0-FontWeightBoldLabel"Last Name"-Row0-Column1-FontWeightBoldTextBox-Row1-Column0-Margin5-NameFirstNameTextBox-Row1-Column1-Margin5-NameLastNameButton"Unlock Account"-On_Click{$Window|Set-UIValue-passThru|Close-Control}-IsDefault-Margin5-Row2-Column0-ColumnSpan2}}Get-UserInfo# Returns and Prints the hashtable@"
Name Value
---- -----
FirstName Mister
LastName Trouble
"@
Pressing the button returns a Hash Table
Here is I how I set this up to work. I named the TextBox controls FirstName and LastName. Then in the Button –On_Click event, I pipe the $Window automatic variable to the ShowUISet-UIValue cmdlet. Set-UIValue takes the content of the TextBox and copies it to the Tag properties. Then, when the form is closed, via Close-Control, the Tag properties are scanned and the name and tag of that control are added to the hash table as a key value pair.
Variable Splatting
Hashtables (aka associative arrays) are great data structures. Plus, in PowerShell you can use them to do variable splatting.
To do this is, when referencing the variable that you want to pass to the command, you use @ instead of $ as the prefix to the variable.
Conclusion
So, I can squirrel away my Get-UserInfo function and reuse it. Then, calling the Get-QADUser cmdlet becomes even simpler.
$userInfo=Get-UserInfoGet-QADUser@userInfo
This approach has another benefit. I can add another TextBox to my GUI, name it the same name as a parameter on Get-QADUser and it will seamlessly work.
These are some of the high order abstractions I and my fellow ShowUI authors, James Brundage and Joel Bennett, are building into ShowUI.
Give it a try and drop us line on CodePlex or our blogs if you have questions or suggestions.
I ported his code to ShowUI and focused on the elements he did:
Control resizing (Using the Grid)
Adding controls to a Window
Attaching events (On_Click parameter for the button)
Changing control fonts (FontFamily parameter for the text box)
Using WinForms and PowerShell are a great approach to building GUIs. One advantage WinForms has over ShowUI is it is available on any machine you deliver your PowerShell script to.
ShowUI leverages WPF and while it requires investment and a module, the value per line of code is compelling.
ShowUI is a PowerShell module to help build WPF user interfaces in script. ShowUI makes the complicated world of WPF easy to use in PowerShell. You can use ShowUI to write simple WPF gadgets, quick front ends for your scripts, components, and full applications.
The conditions under which our Armed Forces conduct operations are rapidly changing with the spread of blogs, social networking sites, and media sharing technology (such as YouTube), and further accelerated by the proliferation of mobile technology.
In a millisecond, millions of people of people all over the world can know everything about everything and everyone. – Jeffrey Gitomer
Changes to the nature of conflict resulting from the use of social media are likely to be as profound as those resulting from previous communications revolutions. The effective use of social media has the potential to help the Armed Forces better understand the environment in which it operates and to allow more agile use of information in support of operations.
Node.js V0.5.1 released a Windows binary. Download the Windows Build.
PowerShell
Here is an example of a web server written in Node which responds with "Hello World" for every request.
This is a single PowerShell script that saves the JavaScript to a file, launches node and then uses the .NET framework Net.WebClient to make a request.
A question I often get about PowerShell from ex-UNIX developers is whether or not PowerShell can “tail” files. Unfortunately, there is no direct analogy to the tail command in PowerShell. It’s typically used to watch the contents of a log file live as it is added to, and that is certainly something that PowerShell can do.
This question comes from a developer who is using NLog to log messages from his app involving Reactive Framework code.
Get-Content –Wait C:\Test.txt
Get-Content is a PowerShell cmdlet (aliased to type (for DOS people) and cat (for Unix people)). It gets the content of the item at the location specified by the path, such as the text in a file. It reads the content one line at a time and returns a collection of objects, each of which represents a line of content.
The –Wait parameter waits for content to be appended to the file. If content is appended, it returns the appended content.
Out-GridView
You can pipe the results of PowerShell to a grid view window where the output is displayed in an interactive table. Out-GridView is available out of the box.
Features of Out-GridView
Hide, Show, and Reorder Columns
Sort
Quick Filter
Criteria Filter
Copy and paste
How To
Get-Content –Wait c:\test.txt | Out-GridView. As the data is updated from the background task (see code below), another line is added to the table. You can even do a quick filter and as the lines are appended to the file, Out-GridView adds them applies the filter to the new information.
Bart clearly explains what Ix is and why they’ve built this library, what it’s for, and when to go interactive. This is a deep conversational piece with plenty of whiteboarding during which we also talk about the current status of IQbservable.
I posted PowerShell Clock with ShowUI. Ravi, another PowerShell MVP, tried the sample using the AsJob parameter. The AsJob will run the PowerShell WPF GUI in the background. Unfortunately, the FontSize and other parameters would not set correctly and the clocked was not readable.
Definitely check it out, he kicks it up a notch with data context’s, PowerShell DataSources. splatting, adding event handlers and more.
Here is my updated clock code
Run it with either –Show or –AsJob
HippyDippy-Clock-ShowHippyDippy-Clock-AsJob
functionHippyDippy-Clock{param([string]$Name,[Int]$Row,[Int]$Column,[Int]$RowSpan,[Int]$ColumnSpan,[Int]$Width,[Int]$Height,[Double]$Top,[Double]$Left,[Windows.Controls.Dock]$Dock,[Switch]$Show,[Switch]$AsJob)begin{ipmoshowui}process{if(-not$psBoundParameters.Background){$psBoundParameters.Background='Transparent'}$uiParameters=@{}+$psBoundParametersBorder@uiParameters-On_Loaded{$this.Child=Grid-Columns150,300*{Image-Source"http://weaselzippers.us/wp-content/uploads/2011/05/hippie.jpg"-Column0Label-NameTarget-FontSize90-Column1`
-FontFamily"Impact, Arial"-FontWeight800-Foreground(LinearGradientBrush$(GradientStop-ColorRed-Offset1GradientStop-ColorOrange-Offset0.85GradientStop-ColorYellow-Offset0.7GradientStop-ColorGreen-Offset0.55GradientStop-ColorBlue-Offset0.4GradientStop-ColorIndigo-Offset0.2GradientStop-ColorViolet-Offset0))}$this.DataContext=Get-PowerShellDataSource-On_OutputChanged{$output=Get-PowerShellOutput-Last-OutputOnly$Target.Content=$output}-Script{while($true){(Get-Date).ToString('T');Start-Sleep-Seconds1}}}-On_Initialized{$window.SizeToContent='WidthAndHeight'$window.WindowStyle='None'$window.Background='Transparent'$window.AllowsTransparency=$true$window.WindowStartupLocation='CenterScreen'Add-EventHandler-EventName"On_Closing"-Handler{if($this.Content.DataContext.Command.Stop){$this.Content.DataContext.Command.Stop()}}-Object$window# When the right mouse button is down, close the control Add-EventHandler-EventName"On_PreviewMouseRightButtonDown"-Handler{$_.Handled=$trueClose-Control}-Object$windowAdd-EventHandler-EventName"On_PreviewMouseLeftButtonDown"-Handler{$_.Handled=$true$this.DragMove()}-Object$window}}}
Doug Finke is a Microsoft Most Valuable Professional (MVP) for PowerShell. He lives and works in New York City building applications for the financial industry. Read more about Doug...