Posts Tagged ‘WPF’
PowerBoots 0.3 – The Faster Edition
I’ve been working on a ton of new functionality for this next release of PowerBoots … and now that I’m getting close to ready to release, I thought it was time to work on the performance! Here’s a completely trivial example:
WPK:
Command : $boxes = 1..100 | % { New-TextBox -Text Foo -FontFamily Consolas -On_GotFocus { $_ } }
Duration : 5.25153s
Current PowerBoots 0.2:
Command : $boxes = 1..100 | % { TextBox -Text Foo -FontFamily Consolas -On_GotFocus { $_ } }
Average : 9.40994s
You can see why I thought I should probably work on improving that. It was bad.
PowerBoots 0.3 yesterday:
Command : $boxes = 1..100 | % { TextBox -Text Foo -FontFamily Consolas -On_GotFocus { $_ } }
Duration : 7.43874s
PowerBoots 0.3 tonight:
Command : $boxes = 1..100 | % { TextBox -Text Foo -FontFamily Consolas -On_GotFocus { $_ } }
Duration : 0.34103s
Now, if you’re like me, you’re probably thinking I screwed up something and that TextBox isn’t actually getting created right …

Postscript: ran another test. A little more useful. I have 248 fonts on my system. I have an “Samples” script which shows them all:
New-BootsWindow { ScrollViewer { TextBlock "Loading Fonts..." -FontSize 62 -FontFamily SegoeUI } } -Async -Passthru |
Invoke-BootsWindow -Script {
$This.Content.Content = $(
ForEach( $font in [System.Windows.Media.Fonts]::SystemFontFamilies ) {
TextBlock -FontFamily $font.Source -Text "The Quick Brown Fox Jumps over the Lazy Dog" -FontSize 18; Write-Host $font
}
) | StackPanel
}
Old PowerBoots:
Duration : 19.39894s
New PowerBoots:
Duration : 3.53100s
Creating WPF UIs for PowerShell with PowerBoots and Visual Studio WPF Designer
I’ve had several people ask me how PowerBoots compares to PrimalForms, or ask for a visual designer for PowerBoots. I usually answer something along the lines of the fact that Microsoft has already created a very good WPF/XAML designer in Visual Studio (including the free Express editions), particularly in 2010, so I don’t see why I should duplicate their efforts. However, up until now I haven’t written or published any sort of walk through about how to make that work …
So crank up your Visual Studio Express Edition and make yourself some user interfaces!
Basically, you just create a WPF project in C# or VB.Net or whatever … I chose to name my project “XamlForBoots” — your project will start off with an empty MainWindow.xaml file which will look something like this:
After you drag a few more controls onto the form, and you’ve created a complete user interface, you should delete the x:Class attribute. You need to make sure you know the name of the controls you want to interact with, so you might end up with something like this (I used the property pane, which you can’t see in this shot, to name each textbox and the button):
At this point, we’re ready to drop into PowerShell and write some script. Now … there is one catch here. The first script I’m going to show you here is for PowerBoots 0.3 (which will be the first release candidate for a gold 1.0 release, and will be out soon™). However, I’ll post below some code to make it work on the current release, but it requires an external function.
So, in the next release, you can just do something like this:
Register-BootsEvent -InputObject $Calculate -EventName Click -Action {
$Total.Text = '${0:n2}' -f (($Miles.Text -as [Double]) / ($Mpg.Text -as [Double]) * ($Cost.Text -as [Double]))
}
}
The key thing you’re supposed to notice here is that the named controls in the XAML are automatically surfaced as variables in the event handlers, and all you have to do is write your logic and hook it up to the controls. We provide a Register-BootsEvent cmdlet which is like Register-ObjectEvent except that it executes the event handlers on the UI thread (so they can do things to the UI) instead of in a new runspace, but basically it’s like calling Add_Click. Of course, you can use Register-ObjectEvent if you just want to spin off PowerShell tasks that don’t read/write the UI.
Backwards compatibility
To get this to work in the current release, you need a function Export-NamedControl to create variables for each of those named controls as variables. Once you’ve defined that function, you can write code very much like I did before, but you have to call Export-NamedControl yourself, and you won’t have that Register-BootsEvent cmdlet. You don’t really need it for this anyway, so that’s not a big deal, at least in this case. Here’s the function. and the actual code to create the window. You can just paste this into a script file:
[CmdletBinding()]
param(
[Parameter(ValueFromPipeline=$true, Position=1, Mandatory=$true)]
$Root = $BootsWindow
)
process {
Invoke-BootsWindow $Root {
$control = $BootsWindow
while($control) {
$control = $control | ForEach-Object {
$Element = $_
if(!$Element) { return }
Write-Verbose "This $($Element.GetType().Name) is $Element"
if($Element.Name) {
Write-Verbose "Defining $($Element.Name) = $Element"
Set-Variable "$($Element.Name)" $Element -Scope 2
}
## Return all the child controls ...
@($Element.Children) + @($Element.Child) + @($Element.Content) +
@($Element.Items) + @($Element.Inlines) + @($Element.Blocks)
}
}
}
}
}
####################################################################################################################
## Create the window and hook the click. Make sure to use full paths
New-BootsWindow {} -FileTemplate $pwd\MainWindow.xaml -On_Loaded {
Export-NamedControl -Root $Args[0]
$Calculate.Add_Click({
$Total.Text = '${0:n2}' -f (($Miles.Text -as [Double]) / ($Mpg.Text -as [Double]) * ($Cost.Text -as [Double]))
})
}
And in order to try my demo, you’re going to need that MainWindow.xaml file:
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Trip Cost">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="28" />
<RowDefinition Height="28" />
<RowDefinition Height="28" />
<RowDefinition Height="28" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="110" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label Content="Miles" VerticalAlignment="Top" />
<TextBox Grid.Column="1" Height="23" Width="200" Name="miles" HorizontalAlignment="Stretch" />
<Label Grid.Row="1" Content="Miles per Gallon" VerticalAlignment="Top" />
<TextBox Grid.Column="1" Grid.Row="1" Height="23" Width="200" HorizontalAlignment="Stretch" Name="mpg" />
<Label Grid.Row="2" Content="Cost per Gallon" VerticalAlignment="Top" />
<TextBox Grid.Column="1" Grid.Row="2" Height="23" Width="200" HorizontalAlignment="Stretch" Name="cost" />
<Button Name="calculate" Grid.Row="3" Content="_Calculate" HorizontalAlignment="Center" />
<TextBlock Grid.Column="1" Grid.Row="3" Height="23" Width="200" HorizontalAlignment="Stretch" Name="total" />
</Grid>
</Window>
WPF in PowerShell: PowerBoots 0.2
I’ve finally given over trying to improve PowerBoots for this iteration of development, and in between setting up the ScriptingGames.PoshCode site and releasing the PoshCode software on the main PoshCode.org site (it’s coming, I promise), I decided to take a few minutes and release this lates PowerBoots, and it’s a ground-breaking release, if I do say so myself!
PowerShell 1.0 Compatibility
There are three huge changes in this release, actually. But the biggest one is that most of the functionality works in the released version of PowerShell 1.0! There are still a few glitches and bugs when it’s running in 1.0, but I’ve decided it’s past time I just release it and let you start using it! If you use it on 1.0, please let me know if you run into anything weird, or problems you can’t figure out workarounds for.
Cached Script Functions!
The second biggest change is that all of the functions are now cached. The first time it’s loaded, PowerBoots actually writes out a few hundred scripts files into a “Functions” subfolder, and from then on, they’re only loaded when they’re used — saving you a lot of time at startup, and a lot of memory. Additionally, when you load in additional controls, such as the Visifire WPF chart controls, those functions are cached permanently too, so you never even have to manually load the assembly again!
Dependency Properties
A few people have asked over the last few months about how to set attached properties and dependency properties in WPF from PowerShell, so in this release I’ve included full support for these in a way that will, I hope, simply work so well it will boggle your mind
All you have to do to tell a control, for instance, to be in the 3rd column of a grid is to just pass Button "Click Me" -"Grid:Column" 2 … it’s THAT simple. In fact, for properties that have unique names, you don’t even have to specify the type, just the name, like -Row 3 to specify the grid row.
Regression and Backwards Compatibility
Of course, the downside of these changes is that some of the syntax has changed a little bit. All scripts and event handlers (ie: click handlers for WPF Buttons) are run from the dll module scope in PowerShell 2 (the global scope in PowerShell 1), which means that they can’t access “script” scope variables from your scripts (which ends up meaning you have to declare a lot of things global that you could leave in script scope before). Just to be clear on the quality of this release: once we have ironed out the minor problems we’re having with PowerShell 1.0 in a way that I’m comfortable with, I expect to push the version number up and release an 1.0 Release Candidate, barring any major issues.
In order to help with the transition, I’ve included a Samples.ps1 script which has 28 sample scripts in it (mostly from the original Tutorial Walk-through, which I will update soon). I’ve updated each of them to work with this release, in both PowerShell 1 and PowerShell 2 (which means they’re almost all written in PowerShell 1 syntax), so you can use them as good examples of how to get things done!
Please use the Discussions Forum and Issue Tracker on the CodePlex site to post any problems you have, and I’ll try to write up a few more posts describing changes and differences in the next couple of weeks.
Related articles by Zemanta
- PowerBoots: Loading XAML Windows in PowerShell 1.0 or 2.0 (huddledmasses.org)
- PowerBoots: PowerShell GUIs are now multi-threading (huddledmasses.org)
- PingMonitor: interactive WPF UIs from PowerShell (1.0 or 2.0) (huddledmasses.org)
PowerBoots: The tutorial walkthrough
Updated to PowerBoots 0.1
An introduction to PowerBoots
Please excuse me if I start by just copying the basic ideas of the Shoes Tutorial, but I figured that since PowerBoots is inspired by Shoes, that was as good a place as any to start. PowerBoots (or just “Boots”) is a PowerShell 2.0 module with functions for writing Windows Presentation Framework (WPF) applications in the PowerShell scripting language. You should get the latest version of PowerBoots before continuing, and install it by putting the “PowerBoots” folder in one of your “Modules” folders (list them by typing $Env:PSMODULEPATH in PowerShell v2).
Don’t forget to start PowerShell.exe with the STA parameter (This is no longer required in PowerBoots 0.1).
Did I hear someone ask what is WPF? It was introduced as part of .Net 3.0 (and vastly improved in .Net 3.5), so you can expect to find it preinstalled on computers from Vista on, and of course you can download and install it on XP if it’s not already installed. The only thing you really need to know about WPF for the purposes of this tutorial is that it is the new GUI toolkit for .Net, and that it is container based — you put elements into other elements to control the layout, rather like HTML and Java Swing… you can pick up the rest as we go along.
A simple Boots program

New-BootsWindow -SizeToContent WidthAndHeight -Content (
Button -Content "Push Me"
)
The parenthesis ( and ) are a container, so the button is “in” the Window. You can also pass a ScriptBlock instead, which works basically the same way. Of course, this is a bit uglier than the Shoes syntax, so lets see if we can’t clean it up some. The -Content parameter is positional, so the first non-named argument you pass will be used for that. The same is true for the -Children parameter of panels, and in fact, each of the other similar parameters: Items, Blocks, and Inlines.
We have used a function New-BootsWindow which has an alias Boots. Boots takes all the same parameters as the Window function mentioned previously, but it uses slightly more useful defaults, and has a few other major benefits as well, the first of which is that it automatically “shows” the window, and the second is that it supports an -Async parameter which allows the window to come out in a new thread so that you can continue using PowerShell while the window remains alive and responsive. There is one catch: New-BootsWindow cannot take it’s content on the pipeline (the old function, now renamed “Out-BootsWindow” can take pipeline content, but is a script function, and requires -STA mode) — you have to specify it as a ScriptBlock. So now that we know this, we can rewrite our first example like this:
Boots { Button -Content "Push Me" }
Just for the record, the simplest Boots program would just be a simple popup dialog to put some text in a Window, like: Boots { $msg } …
We can put controls in a stack

Boots {
StackPanel {
Button "A bed of clams"
Button "A coalition of cheetas"
Button "A gulp of swallows"
}
}
StackPanels are awesome. So are WrapPanels. Try that code with a WrapPanel instead of a StackPanel and see what the difference is. This brings up another point: those positional parameters we mentioned earlier: Content, Children, Items, Blocks, and Inlines, are also set to accept the value from the pipeline. Not only that, but they are intelligent about whether or not the content model accepts multiple items! So we can actually rewrite that script like this, and get the same results:
Boots { "A bed of clams", "A coalition of cheetas", "A gulp of swallows" | Button | StackPanel }
Now we’re really onto something! Read the rest of this entry »
PowerBoots: Loading XAML Windows in PowerShell 1.0 or 2.0
Awhile back I wrote a series of posts about WPF From PowerShell From PowerShell” which were about how you could load XAML in previous PowerShell 2 CTPs to create WPF user interfaces … a few people have mentioned loading XAML in PowerBoots, and a couple of people have posted other samples showing XAML even since I published the most recent release, so I figure it’s time to point out that you really can load that XAML into Boots, and get all the threading and other support.
Just for fun, I’m going to rehash an earlier post about updating windows to show how you can go about this using PowerBoots, and hopefully show that it’s a little easier (and a lot more async). Compare and contrast the code in this article with that one, just for fun.
This works with any version of PowerShell
Unlike the original article, most this code (except where explicitly mentioned) works on either PowerShell v2 with PowerBoots, or PowerShell 1.0 with PoshWPF, a snapin that is part of the PowerBoots module but is also released separately… Also, unlike those previous posts, this does not require you to be running PowerShell.exe with the -STA switch, since the New-BootsWindow cmdlet takes care of threading for us.
Read the rest of this entry »
PowerBoots and Attached Properties
WPF uses a concept called “Attached Properties” to handle certain things, like when you put controls into a DockPanel. Basically, anything you put inside a DockPanel has a property “Dock” which you can set … but because the property is actually defined by the DockPanel, it doesn’t show up in PowerBoots, so you can’t just say -Dock "Bottom" when you create the child items … at least, not yet.
I’m still thinking about the best way for me to expose this in PowerBoots, because the problem is that attached properties can get attached several ways, and not just on direct children of an element. So I wanted to show you a way that you can do it for now so you can at least use the DockPanel effectively:
DockPanel -LastChildFill $true {
DockPanel -LastChildFill $true {
Button "OK" -Padding "2,0,2,0" |
ForEach-Object { $_.SetValue(
[System.Windows.Controls.DockPanel]::DockProperty,
[System.Windows.Controls.Dock]::Right)
$_
}
TextBox -HorizontalAlignment Stretch
} | ForEach-Object { $_.SetValue(
[System.Windows.Controls.DockPanel]::DockProperty,
[System.Windows.Controls.Dock]::Bottom)
$_
}
TextBox -AcceptsReturn $true -minWidth 300 -minHeight 200
}
}
A better way …
Here’s what I’m thinking about for the next release of PowerBoots (you can take this and use it now, if you like it, but I’m really looking for, uhm … better ideas). Basically, I have written a function: Set-AttachedProperty, which takes an attached property and a value, and passes through the element on the pipeline. You may want to use this in conjunction with the module I published awhile back for creating type accelerators, because it lets you run a line like this:
Which will let you substitute [DockPanel] for [System.Windows.Controls.DockPanel] … and of course, you can use it for all the types you want to use attached properties from, and it’s a real lifesaver if you need to use a bunch of them. Of course, in this particular example, we really only need to use a single attached property, so it’s enough to define that property ahead of time:
Then you can use the Set-AttachedProperty function through an alias sap, and rewrite that huge block above like this:
DockPanel -LastChildFill $true {
DockPanel -LastChildFill $true {
Button "OK" -Padding "2,0,2,0" | sap $DockProperty Right
TextBox -HorizontalAlignment Stretch
} | sap $DockProperty Bottom
TextBox -AcceptsReturn $true -minWidth 300 -minHeight 200
}
}
Pretty slick, right? And it will even print out the list of values in the error message if you invoke it with an invalid value against an enum property like dock: sap $DockProperty "" … The problem I have with it is that you have to predefine your $DockProperty variable, and you can’t just define it against the root class. So I’m trying to find a way to tweak the dynamic property generation to make it so that the pipe into | sap $DockProperty Bottom can just be a parameter to the original element: -Dock Bottom … if I can’t find that, in the worst case scenario, I’ll just add an -AttachedProperties parameter with a hashtable of $DockProperty,“Bottom” or something … what do you think?
In any case, here’s the sap function, for now, and remember to use it as part of the pipeline:
function Set-AttachedProperty {
[CmdletBinding()]
PARAM(
[Parameter(Position=0,Mandatory=$true)
[System.Windows.DependencyProperty]
$Property
,
[Parameter(Mandatory=$true,ValueFromPipeline=$true)
$Element
)
DYNAMICPARAM {
$paramDictionary = new-object System.Management.Automation.RuntimeDefinedParameterDictionary
$Param1 = new-object System.Management.Automation.RuntimeDefinedParameter
$Param1.Name = "Value"
# $Param1.Attributes.Add( (New-ParameterAttribute -Position 1) )
$Param1.Attributes.Add( (New-Object System.Management.Automation.ParameterAttribute -Property @{ Position = 1 }) )
$Param1.ParameterType = $Property.PropertyType
$paramDictionary.Add("Value", $Param1)
return $paramDictionary
}
PROCESS {
$Element.SetValue($Property, $Param1.Value)
$Element
}
}
New-Alias sap Set-AttachedProperty
PowerBoots: PowerShell GUIs are now multi-threading
Announcing the release of PowerBoots 0.1
This release of PowerBoots is the most exciting release software I’ve cranked out in awhile. It finally has almost all of the features that I have thought of so far (we’re still missing proper support for attached properties).
- You can create pretty much any WPF element, including ones I haven’t thought of adding yet (use Add-BootsFunction to add a new assembly or a single type).
- You can create graphical user interfaces from PowerShell 1.0 all the way to the latest PowerShell 2.0 CTP.
- You can create your WPF GUIs
-Asyncin their own threads, or inline in PoshConsole, or as synchronous dialogs that return values when they close. - You can capture screenshots of your UIs (eg: generate .jpg charts from Visifire). You can even do so without displaying them!
- You can take advantage of XAML Data Templates to generate graphical representations of any objects in the PowerShell pipeline.
- You can add to, or modify your running GUIs from the command line.
You can read the “and much much more” between the lines right?
Read the rest of this entry »
PowerBoots – Output Graphs to Images from PowerShell
Once I started playing with the new ability, introduced in PowerBoots 0.0.4 to easily add support for new graphical controls to PowerBoots, I found all sorts of fun widgets out there in open-source land. I’ll write about a few of them in the future, but for now I’m just going to stick with Visifire. After playing with a few examples, I finally got around to actually trying to create the graphs I needed at work which were the main source of motivation for trying to do Visifire from PowerShell anyway …
The problem was, half of the need we have for graphs is to throw them up on a web-server … so I needed a way to take the WPF window, and capture the controls and visuals as an image. Basically, render the WPF control to a bitmap image, instead of to the screen. To cut a long story short, I figured it out of course — why else would I be writing this? (get it here).
Out-BootsImage
So the new version of PowerBoots includes the Out-BootsImage function (aliased as BootsImage and “obi”), which basically is designed to take the filename of an image, and a boots visual element, and create a screenshot. It can generate bmp, gif, jpg, png, tiff, and even Microsoft’s new wdp format, or it can output to clipboard.

It’s late, so I’m not going to write any more about this … the bottom line is, if you have been looking for a (free) way to generate graphs and charts to image files in PowerShell, this will work for you: go grab Visifire, check out their gallery for inspiration, and start churning out graphs! Just for fun, here are the samples from the help documentation (except, this is the actual script I ran, including the upload code) with screen-shots …
Important note
When producing images of Visifire charts using this method, it is absolutely critical that you must specify -Animation $false because otherwise you will consistenly produce images of empty charts (since by default Visifire animates all of the bars onto the screen right after the SourceInitialized event that I use to capture the image). Oh, and if you need to remove the Visifire.com watermark, there is a -watermark $false parameter on the Chart element, which turns it off.

$credential = Get-Credential
Chart -Width 200 -Height 150 -Theme Theme3 -Watermark $false -Animation $false (
DataSeries $(
1..(Get-Random -min 3 -max 6) | ForEach-Object {
DataPoint -YValue (Get-Random 100)
}
)
) | Out-BootsImage VisiFire-BootsImage.jpg |ForEach-Object {
Send-FTP HuddledMasses.org $credential -LocalFile $_ -Remotefile "$imgPath/$($_.Name)"
[Windows.Clipboard]::SetText( "!http://huddledmasses.org/images/PowerBoots/$($_.Name)!" )
}
StackPanel -Margin "10,5,10,5" $(
Label "Please enter your name:"
StackPanel -Orientation Horizontal $(
TextBox -OutVariable global:textbox -Width 150 -On_KeyDown {
if($_.Key -eq "Return") {
Write-Output $textbox[0].Text
$BootsWindow.Close()
}
}
Button "Ok" -Padding "5,0,5,0" -Margin "2,0,0,0" -On_Click {
Write-Output $textbox[0].Text
$BootsWindow.Close()
}
)
) | Out-BootsImage BootsImage-Screenshot.jpg | ForEach-Object {
Send-FTP HuddledMasses.org $credential -LocalFile $_ -Remotefile "$imgPath/$($_.Name)"
[Windows.Clipboard]::SetText( "!http://huddledmasses.org/images/PowerBoots/$($_.Name)!" )
}
PowerBoots 0.0.4 – Tab Completion – Visifire
This is the fourth release of the PowerBoots module for PowerShell 2 (Download – 7z). PowerBoots is a framework for creating WPF GUIs from PowerShell, and this latest release brings a couple of bug fixes and two new features.
Now with tab completion
The biggest change in PowerBoots 0.0.4 is that tab-completion for parameters works in the shell.
Behind the scenes what has happened is that I’ve discovered that in the current CTP3 release of PowerShell 2, Dynamic Parameter sets are not handled correctly for aliases, and the Get-Command for aliases of functions doesn’t return the same set of parameters as it does on the function itself. The result is that Tab-Completion for dynamic parameters doesn’t work on aliases (neither the built-in tab completion, nor MoW’s PowerTab). I wrote up a bug against that, but I also found that I can work around it by creating hundreds of functions (all pointed at the same script-block), instead of hundreds of aliases (all pointed at the same function).
PowerBoots produces functions instead aliases
This means the PowerBoots commands show up by default when you run Get-Command. Incidentally, this means that the first time you run Get-Command after you Import-Module PowerBoots you incur a huge penalty (17 seconds on my machine) while Get-Command caches all the dynamic parameter information about the functions. NOTE: because of the DynamicParam bug, I’ve ditched aliases altogether for this particular project and am generating two functions for each element/type in PowerBoots: the full New-Namespace.Type version, and a “Type” alias when possible. Trust me when I say: “it’s worth it” ... with the backing scriptblock, there’s virtually no difference between the two approches in terms of resources (other than the aforementions hit on Get-Command).
Now with more controls
The second big change (and the one which I hope will have the biggest long-term impact) is that you can now import your own WPF control libraries into PowerBoots. This means that you can, for example, go get the open source Visifire charting library, extract their WPFVisifire.Charts library into your PowerShell folder, and use it like so:
Add-BootsContentProperty 'DataPoints', 'Series'
Add-BootsFunction -Assembly "~\Documents\WindowsPowershell\Libraries\WPFVisifire.Charts.dll"
Chart -Width 200 -Height 150 -Theme Theme3 (
DataSeries $(
DataPoint -YValue (Get-Random 100)
DataPoint -YValue (Get-Random 100)
DataPoint -YValue (Get-Random 100)
DataPoint -YValue (Get-Random 100)
)
) | Boots -Title "Sample, Theme 3"
More PowerBoots: PowerShell and Out-WPF
I’m almost ready to release a version of Out-WPF which will work on both my PoshConsole host (embedding in the host when appropriate) and on PowerShell.exe, both in CTP3 and in v1 … but since Jeffrey outed my little video demo, I figured I might as well share it here. Read the rest of this entry »
![Reblog this post [with Zemanta]](http://img.zemanta.com/reblog_e.png?x-id=3373c251-af5f-4875-a3fa-7f0c2581d019)