#requires -version 2 ## Out-BarGraph.ps1 ## A script to generate WPF bargraphs using XAML ## REQUIRES graph.xaml ( included here as a DATA section ) ######################################################################################################################## ## Example Usage ## ls | Out-BarGraph "File Sizes in Bytes" -Label {$_.Name} -Value {$_.Length} ######################################################################################################################## ## Version History ## 1.4 - Embedded XAML in script ## 1.3 - Added [scriptblock] parameters, removing need for data to be a custom psobject ## 1.2 - Wrapper script now sets all values ## 1.1.3 - Added data-bound "scale" labels ## 1.1.2 - Added data-bound caption ## 1.1.1 - Added data-bound labels ## 1.1 - Got data-binding to the graph working ## 1.0 - First working version, no live data binding ######################################################################################################################## Param( $caption= "A bar-graph from WPF", $data = @(), [scriptblock]$Label = $(Throw "You must specify the 'Label' scriptblock"), [scriptblock]$Value = $(Throw "You must specify the 'Value' scriptblock"), [switch]$sideways ) BEGIN { function Out-GraphableXml ($data, [ref]$max, [scriptblock]$Label, [scriptblock]$Value) { ### Get a "Max" number which should be the next big round number (eg: 5,10,50,100,150 ...) $max.Value = ($data | Sort-Object {&$Value -as [double]} -Desc | Select-Object @{n="Value";e=$Value} -First 1).Value -as [double] if( $max.Value -gt 1 ) { $siz = [Math]::Pow( 10, [Math]::Truncate($max.Value).ToString().Length -1 ) / 2 } else { $siz = (.5 / (10 * ($max.Value.ToString().Length - 2 - $max.Value.ToString().TrimStart("0.").Length))) } $max.Value = [Math]::Ceiling( $max.Value / $siz ) * $siz ## Export the data ... $path = [IO.Path]::GetTempFileName() $data | Select-Object @{n="Value";e=$Value},@{n="Label";e=$Label},@{n="Percent";e={($_ | &$Value)/$max.Value}} | export-clixml $path return $path } } PROCESS { if($_) { $data += $_ } } END { Write-Host "Loading XAML window..." -fore Cyan ### Import the WPF assemblies Add-Type -Assembly PresentationFramework Add-Type -Assembly PresentationCore ## I've removed the xaml to a separate document because it's getting too big for my example :) $graph = [Windows.Markup.XamlReader]::Load( (New-Object System.Xml.XmlNodeReader ([Xml](Get-Content "graph.xaml"))) ) $graph.Resources.Data.Source = Out-GraphableXml $data ([ref]$max) $Label $Value ### Generate 10 labels ... $graph.Resources.scale.Document = &{ "" 10..1 | ForEach-Object { "" } "" } ### And set the caption $graph.Resources.GraphCaption = $caption ### Maybe rotate the whole thing if($sideways) { $graph.Resources.Sideways.Angle = 90 } $graph.ShowDialog() # Don't forget to delete that temp file... Remove-Item $graph.Resources.Data.Source.AbsolutePath }