PoshCode Logo PowerShell Code Repository

WPF PingMonitor for 1.0 (modification of post by view diff)
View followups from Joel Bennett | embed code: <script type="text/javascript" src="http://PoshCode.org/embed/980"></script>download | new post

This script should work in PowerShell 1.0 and 2.0, even without -STA (single threaded apartment) mode.
A PowerBoots script to demonstrate the power of PoshWpf: Create a New-PingMonitor window which uses Visifire charts to display the recent ping history of multiple servers simultaneously. There are only two callable functions here:

  1. if(!(Get-Command New-BootsWindow -EA SilentlyContinue)) {
  2.    Add-PsSnapin PoshWpf
  3.    #Import-Module PowerBoots
  4.    #Add-BootsContentProperty 'DataPoints', 'Series'
  5.    [Void][Reflection.Assembly]::LoadFrom( (Convert-Path (Resolve-Path "~\Documents\WindowsPowershell\Libraries\WPFVisifire.Charts.dll")) )
  6.    #Add-BootsFunction -Assembly "~\Documents\WindowsPowershell\Libraries\WPFVisifire.Charts.dll"
  7.    #Add-BootsFunction ([System.Windows.Threading.DispatcherTimer])
  8. }
  9.  
  10. if(Get-Command Ping-Host -EA SilentlyContinue) {
  11.    $pingcmd = { (Ping-Host $args[0] -count 1 -Quiet).AverageTime }
  12. } else {
  13.    $pingcmd = { [int]([regex]"time=(\d+)ms").Match( (ping $args[0] -n 1) ).Groups[1].Value }
  14. }
  15.  
  16. $global:onTick = {
  17. Param($window=$global:pingWindow)
  18.    Invoke-BootsWindow $window {
  19.       try {
  20.          foreach($s in $window.Content.Series.GetEnumerator()) {
  21.             $ping = &$pingcmd $s.LegendText
  22.             $points = $s.DataPoints
  23.             foreach($dp in 0..$($points.Count - 1))
  24.             {
  25.                if(($dp+1) -eq $points.Count) {
  26.                   $points[$dp].YValue = $ping
  27.                } else {
  28.                   $points[$dp].YValue = $points[$dp+1].YValue
  29.                }
  30.             }
  31.          }
  32.       } catch {
  33.          Write-Output $_
  34.       }
  35.    }
  36. }
  37.  
  38. function Add-PingHost {
  39. PARAM(
  40.    [string[]]$target
  41. ,  [Visifire.Charts.RenderAs]$renderAs="Line"
  42. ,  [Windows.Window]$window = $global:pingWindow
  43. ,  [Switch]$Passthru
  44. )
  45.    if($Window) {
  46.       Invoke-BootsWindow $Window {
  47.          foreach($h1 in $target) {
  48.             Add-PingHostInternal $h1 $renderAs $window
  49.          }
  50.       }
  51.       if($Passthru) { return $Window }
  52.    } else {
  53.       return New-PingMonitor $target $renderAs -Passthru:$Passthru
  54.    }
  55. }
  56.  
  57. function Add-PingHostInternal {
  58. PARAM(
  59.    [string]$target
  60. ,  [Visifire.Charts.RenderAs]$renderAs="Line"
  61. ,  [System.Windows.Window]$window = $global:pingWindow
  62. )
  63.    $start = $(get-random -min 10 -max 20)
  64.    $ds    = New-Object Visifire.Charts.DataSeries
  65.    $ds.LegendText = $target
  66.    $ds.RenderAs   = $renderAs
  67.    [void]$window.Content.Series.Add($ds)
  68.    for($i=0;$i -lt 25;$i++) {
  69.       $dp = New-Object Visifire.Charts.DataPoint
  70.       $dp.YValue = $start
  71.       [void]$ds.DataPoints.Add( $dp )
  72.    }
  73. }
  74.  
  75. function New-PingMonitor {
  76. PARAM (
  77.    [string[]]$hosts = $(Read-Host "Please enter the name of a computer to ping")
  78. ,  [Visifire.Charts.RenderAs]$renderAs="Line"
  79. ,  [Switch]$Passthru
  80. )
  81.    $global:pingWindow = New-BootsWindow -Async {
  82.       Param($window) # New-Boots passes the window to us ...
  83.       Write-Debug "Window: $window"
  84.       # Make a timer
  85.       $timer          = New-Object System.Windows.Threading.DispatcherTimer
  86.       $timer.Interval = "00:00:01.0"
  87.       # Make a new scriptblock of the OnTick handle, passing it ourselves
  88.       $tickover = ({ &$global:onTick $window }).GetNewClosure()
  89.       $timer.Add_Tick( $tickover )
  90.       # Stick the timer into the window....
  91.       $window.Tag = @($timer, $tickover)
  92.      
  93.       # Make a chart
  94.       $PingChart = New-Object Visifire.Charts.Chart
  95.       $PingChart.Height    = 300
  96.       $PingChart.Width     = 800
  97.       $PingChart.watermark = $false
  98.       #$PingChart.Add_Initialized( {$timer.Start();} )
  99.      
  100.       # Make a bunch of data series
  101.       $hosts | % {
  102.          $h1 = $_
  103.          $start = $(get-random -min 10 -max 20)
  104.          $ds    = New-Object Visifire.Charts.DataSeries
  105.          $ds.LegendText = $h1
  106.          $ds.RenderAs   = $renderAs
  107.          $PingChart.Series.Add($ds)
  108.          for($i=0;$i -lt 25;$i++) {
  109.             $dp = New-Object Visifire.Charts.DataPoint
  110.             $dp.YValue = $start
  111.             $ds.DataPoints.Add( $dp )
  112.          }
  113.       }
  114.       # we have to output the chart: whatever we output from here ends up in the window
  115.       $PingChart
  116.    } -On_ContentRendered {
  117.       Write-Debug "Content Rendered. Tag: $($this.tag[0])"
  118.       $this.tag[0].Start()
  119.    } -On_Closing {
  120.       $this.tag[0].Remove_Tick($this.tag[1])
  121.       $this.tag[0].Stop()
  122.       $global:pingWindow = $null
  123.    } -Title "Ping Monitor" -Passthru
  124.    
  125.    if($Passthru) {
  126.       return $global:pingWindow
  127.    }
  128. }

Submit a correction or amendment below (
click here to make a fresh posting)
After submitting an amendment, you'll be able to view the differences between the old and new posts easily.

Syntax highlighting:


Remember me