locked
Charting with Powershell RRS feed

  • Question

  • Hi All,

    I'd like to make a simple bar chart, that shows three different types of data:
    1. the CPU usage of my machine,
    2. the memory usage of a specific process (software),
    3. the connections on a specific port.

    Following is my code. The saved image shows the bars only, without any Y-axis label (the chart's title is OK). What am I doing wrong? (Sorry, I'm not allowed to upload any image yet.)

    Thanks in advance!

    [void][Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms')
    [void][Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms.DataVisualization')
     
    $chart1 = New-Object -TypeName System.Windows.Forms.DataVisualization.Charting.Chart
    $chart1.Width = 1500
    $chart1.Height = 1100
     
    $chartarea = New-Object -TypeName System.Windows.Forms.DataVisualization.Charting.ChartArea
    $chartarea.Name = "ChartArea1"
    $chart1.ChartAreas.Add($chartarea)

    $CPULoad = (Get-WmiObject -computer 192.168.3.4 -class win32_processor | Measure-Object -property LoadPercentage -Average | Select Average).Average
    $Memory = Get-WMIObject Win32_Process -computer 192.168.3.4 | Where-Object{$_.Name -like "xy.exe"} | % {$_.WS/1MB}
    $Memory1 = [Math]::Round($Memory)
    $Connections = Get-NetTCPConnection | Where-Object { $_.LocalAddress -eq "192.168.3.4" -and $_.LocalPort -eq "9977"} | Select-Object LocalAddress, LocalPort | Measure-Object | % {$_.Count}

    [void]$chart1.Series.Add("CPU")
    $chart1.Series["CPU"].ChartType = "Bar"
    $chart1.Series["CPU"].BorderWidth  = 10
    $chart1.Series["CPU"].chartarea = "ChartArea1"
    $chart1.Series["CPU"].color = "blue"
    $chart1.Series["CPU"].Points.addxy("CPU (%)" , $CPULoad)

    [void]$chart1.Series.Add("Memorya")
    $chart1.Series["Memorya"].ChartType = "Bar"
    $chart1.Series["Memorya"].BorderWidth  = 10
    $chart1.Series["Memorya"].chartarea = "ChartArea1"
    $chart1.Series["Memorya"].color = "blue"
    $chart1.Series["Memorya"].Points.addxy("Memory (MB)" , $Memory1)

    [void]$chart1.Series.Add("Connection")
    $chart1.Series["Connection"].ChartType = "Bar"
    $chart1.Series["Connection"].BorderWidth  = 10
    $chart1.Series["Connection"].chartarea = "ChartArea1"
    $chart1.Series["Connection"].color = "blue"
    $chart1.Series["Connection"].Points.addxy("Connection" , $Connections)
     
    $Title = New-Object -TypeName System.Windows.Forms.DataVisualization.Charting.Title
    $chart1.Titles.Add($Title)
    $chart1.Titles[0].Font = "ArialBold, 14pt"
    $chart1.Titles[0].Text = 'Monitoring'

    $chart1.SaveImage("E:\Monitoring\Powershell\Result.png", "PNG")


    • Edited by hcsa1018 Sunday, August 25, 2019 4:34 PM
    Sunday, August 25, 2019 4:31 PM

Answers

  • To better manage the scripting process we need to add error management. This will guarantee that the first error terminates and that it allows us to skip subsequent errors caused by the first error.

    Add-Type -AssemblyName System.Windows.Forms.DataVisualization
    
    function MakeBarSeries {
        Param (
            [string]$Name,
            [int]$Value,
            $Color
        )
        Try{
            $series = $chart1.Series.Add($Name)
            $series.ChartType = 'Bar'
            $series.color = $Color
            $series.Label = $Name
            $series.LabelBackColor = 'Wheat'
            $series.Font = 'ArialBold, 20pt'
            [void]$series.Points.AddY($Value)
        }
        Catch{
            Throw $_
        }
    }
    
    Try{
        # buld the chart container and add initial area
        $chart1 = [System.Windows.Forms.DataVisualization.Charting.Chart]::New()
        $chart1.Size = '1000,600'
        $chart1.Titles.Add([System.Windows.Forms.DataVisualization.Charting.Title]::New())
        $chart1.Titles[0].Font = 'ArialBold, 18pt'
        $chart1.Titles[0].Text = 'Monitoring'
        $chart1.ChartAreas.Add([System.Windows.Forms.DataVisualization.Charting.ChartArea]::New('ChartArea1'))
    
        # obtain data
        $CPULoad = 10
        $Memory1 = 11
        $Connections = 12
    
        # add bars
        MakeBarSeries -Name CPU -Value $CPULoad -Color Blue
        MakeBarSeries -Name Memory -Value $Memory1 -Color Red
        MakeBarSeries -Name Connections -Value $Connections -Color Green
    
        #save image and display
        $imageFile = '.\Result.png'
        $chart1.SaveImage($imageFile,'PNG')
        Start-Process $imageFile
    }
    Catch{
        Throw $_
    }


    \_(ツ)_/


    • Marked as answer by hcsa1018 Sunday, August 25, 2019 8:02 PM
    • Edited by jrv Sunday, August 25, 2019 8:12 PM
    Sunday, August 25, 2019 7:35 PM

All replies

  • Hi,

    before you spend hours on end figuring this out, please do yourself a favour and look at PSHTML and Universal Dashboard.


    Evgenij Smirnov

    http://evgenij.smirnov.de


    Sunday, August 25, 2019 4:45 PM
  • You are not plotting XY values. Review the documentation to understand how to define bars.

    Bars are not XY they are simple measurements displayed along side of each other.


    \_(ツ)_/

    Sunday, August 25, 2019 7:01 PM
  • This will get you closer to what you are trying to do.

    Add-Type -AssemblyName System.Windows.Forms.DataVisualization
    
    function MakeBarSeries {
        Param (
            [string]$Name,
            [int]$Value,
            $Color
        )
        $series = $chart1.Series.Add($Name)
        $series.ChartType = 'Bar'
        $series.color = $Color
        $series.Label = $Name
        $series.LabelBackColor = 'Wheat'
        $series.Font = 'ArialBold, 20pt'
        [void]$series.Points.AddY($Value)
    }
    
    # buld the chart container and add initial area
    $chart1 = [System.Windows.Forms.DataVisualization.Charting.Chart]::New()
    $chart1.Size = '1000,600'
    $chart1.Titles.Add([System.Windows.Forms.DataVisualization.Charting.Title]::New())
    $chart1.Titles[0].Font = 'ArialBold, 18pt'
    $chart1.Titles[0].Text = 'Monitoring'
    $chart1.ChartAreas.Add([System.Windows.Forms.DataVisualization.Charting.ChartArea]::New('ChartArea1'))
    
    # obtain data
    $CPULoad = 10
    $Memory1 = 11
    $Connections = 12
    
    # add bars
    MakeBarSeries -Name CPU -Value $CPULoad -Color Blue
    MakeBarSeries -Name Memory -Value $Memory1 -Color Red
    MakeBarSeries -Name Connections -Value $Connections -Color Green
    
    #save image and display
    $imageFile = '.\Result.png'
    $chart1.SaveImage($imageFile,'PNG')
    Start-Process $imageFile
    


    \_(ツ)_/



    • Edited by jrv Sunday, August 25, 2019 8:13 PM
    Sunday, August 25, 2019 7:24 PM
  • To better manage the scripting process we need to add error management. This will guarantee that the first error terminates and that it allows us to skip subsequent errors caused by the first error.

    Add-Type -AssemblyName System.Windows.Forms.DataVisualization
    
    function MakeBarSeries {
        Param (
            [string]$Name,
            [int]$Value,
            $Color
        )
        Try{
            $series = $chart1.Series.Add($Name)
            $series.ChartType = 'Bar'
            $series.color = $Color
            $series.Label = $Name
            $series.LabelBackColor = 'Wheat'
            $series.Font = 'ArialBold, 20pt'
            [void]$series.Points.AddY($Value)
        }
        Catch{
            Throw $_
        }
    }
    
    Try{
        # buld the chart container and add initial area
        $chart1 = [System.Windows.Forms.DataVisualization.Charting.Chart]::New()
        $chart1.Size = '1000,600'
        $chart1.Titles.Add([System.Windows.Forms.DataVisualization.Charting.Title]::New())
        $chart1.Titles[0].Font = 'ArialBold, 18pt'
        $chart1.Titles[0].Text = 'Monitoring'
        $chart1.ChartAreas.Add([System.Windows.Forms.DataVisualization.Charting.ChartArea]::New('ChartArea1'))
    
        # obtain data
        $CPULoad = 10
        $Memory1 = 11
        $Connections = 12
    
        # add bars
        MakeBarSeries -Name CPU -Value $CPULoad -Color Blue
        MakeBarSeries -Name Memory -Value $Memory1 -Color Red
        MakeBarSeries -Name Connections -Value $Connections -Color Green
    
        #save image and display
        $imageFile = '.\Result.png'
        $chart1.SaveImage($imageFile,'PNG')
        Start-Process $imageFile
    }
    Catch{
        Throw $_
    }


    \_(ツ)_/


    • Marked as answer by hcsa1018 Sunday, August 25, 2019 8:02 PM
    • Edited by jrv Sunday, August 25, 2019 8:12 PM
    Sunday, August 25, 2019 7:35 PM
  • Thanks, this helped a lot.

    I just don't get it, why I (we) can't give different names for different types of data one-by-one on either axis. Do you have perhaps a hint/link that explains this?

    Furthermore, I couldn't find anything on how could I separate the bars in the chart (like "padding" in html/css).

    A big "Thumbs up!" for you.

    Sunday, August 25, 2019 8:09 PM
  • Charts are designed to compare data of the same type - not different types.


    \_(ツ)_/

    Sunday, August 25, 2019 8:10 PM
  • OK, thanks. All I intended to make was, to create a "Monitoring-like graphical process" purely with Powershell. (I'm just a bit above the level of a newbie, I would say. :) )
    Sunday, August 25, 2019 8:19 PM
  • Use "perfmon" as it is designed for basic admin use and requires no programming or scripting skills. It can display and capture actve charts.

    You are trying ot dis[lay three static numbers and charts are designed to display multiple series of numbers over time or some other range.


    \_(ツ)_/


    • Edited by jrv Sunday, August 25, 2019 8:22 PM
    Sunday, August 25, 2019 8:21 PM
  • Here is a simple example of the kind of chart you want but the meaning of the data, in comparison, is suspect.

    Add-Type -AssemblyName System.Windows.Forms.DataVisualization
    
    Try{
        
        # build the chart container and add initial area
        $chart1 = [System.Windows.Forms.DataVisualization.Charting.Chart]::New()
        $chart1.Size = '500,400'
        $chart1.Location = '40,30'
        $chart1.Titles.Add([System.Windows.Forms.DataVisualization.Charting.Title]::New())
        $chart1.Titles[0].Font = 'ArialBold, 18pt'
        $chart1.Titles[0].Text = 'Monitoring'
        $chart1.ChartAreas.Add([System.Windows.Forms.DataVisualization.Charting.ChartArea]::New('Default'))
        
        # obtain data
        $data = @{
            CPU                            = 10
            Memory                         = 11
            Connections                    = 12
        }
        [void]$chart1.Series.Add('Data')
        $chart1.Series['Data'].Points.DataBindXY($data.Keys, $data.Values)
    
        #save image and display
        $imageFile = '.\Result.png'
        $chart1.SaveImage($imageFile,'PNG')
        Start-Process $imageFile
    }
    Catch{
        Throw $_
    }
    


    \_(ツ)_/

    Sunday, August 25, 2019 10:52 PM
  • And just for completeness is how the chart control is designed to be used.

    Add-Type -AssemblyName System.Windows.Forms.DataVisualization
    
    $form = New-Object Windows.Forms.Form
    $form.Text = 'PowerShell Chart'
    $form.Size = '600,600'
    $form.Add_Shown({
        $form.Activate()
    })
    
    
    $form_Load = {
        Try{
            $chart = [System.Windows.Forms.DataVisualization.Charting.Chart]::New()
            $this.controls.add($chart)
            $chart.Name = 'Chart1'
            $chart.Anchor = 'Right,Top,Left'
            
            # build the chart container and add initial area
            $chart.Size = '500,400'
            $chart.Location = '40,30'
            $chart.Titles.Add([System.Windows.Forms.DataVisualization.Charting.Title]::New())
            $chart.Titles[0].Font = 'ArialBold, 18pt'
            $chart.Titles[0].Text = 'Monitoring'
            $area = [System.Windows.Forms.DataVisualization.Charting.ChartArea]::New('Default')
            $chart.ChartAreas.Add($area)
            $area.AxisX.Title = 'Measurements'
            $area.AxisY.Title = 'Measure'
            $chart.BackColor = [System.Drawing.Color]::Transparent
            
            # obtain data
            $data = @{
                CPU                            = 10
                Memory                         = 11
                Connections                    = 12
            }
            $series = $chart.Series.Add('Data')
            $series .Points.DataBindXY($data.Keys, $data.Values)
            $series ['DrawingStyle'] = 'Cylinder'
        }
        Catch{
            Throw $_
        }
    }
    
    # display the chart on a form 
    $form.add_Load($form_Load)
    
    # add a save button 
    $saveButton = New-Object Windows.Forms.Button
    $form.controls.add($saveButton)
    $saveButton.Text = 'Save'
    $saveButton.Location = '500,450'
    $saveButton.Anchor = 'Bottom,Right'
    
    $saveButton.add_click({
        $saveFile = '.\Chart.png'
        $this.FindForm().Controls['Chart1'].SaveImage($saveFile, 'PNG')
        Start-Process $saveFile
    })
    
    $form.ShowDialog()


    \_(ツ)_/



    • Edited by jrv Sunday, August 25, 2019 11:08 PM
    Sunday, August 25, 2019 10:52 PM