Tag Archives: console

PowerShell Console Graphing Revised

Many of you have been having fun with my PowerShell Console Graphing tool I posted the other day. But I felt the need to make one more major tweak. I wanted to have the option for conditional formatting. That is, display graphed entries with high values in one color, medium in another and low in yet another.

The default behavior is still to use a single color. But using ParameterSets I added some new parameters, -HighColor, -MediumColor and -LowColor. They are all mandatory so if you use one parameter you have to define them all.

I also moved the Property parameter and made it positional which should make it easier to use. The conditional coloring works basically by taking the largest possible graph value, which is based on available screen width and dividing it into thirds. The top third is considered high, second third is medium and last third is low.

When it comes time to graph, I check which parameter set we’re using and set the graph color accordingly.

But now I can run a command like this:

out-consolegraph-3

What do you think? Download Out-ConsoleGraph-v2.

UPDATE: A newer version is available at http://jdhitsolutions.com/blog/2013/12/updated-console-graphing-in-powershell/

Graphing with the PowerShell Console

I’ve written before about using the PowerShell console as a graphing tool, primarily using Write-Host. Most of what I’ve published before were really proof of concept. I decided to try and come up with a more formal and re-usable tool that could create a horizontal bar graph based on a numeric property from piped objects. For example, I wanted to get all processes and display a graph of the WorkingSet for each object. My result is an advanced function that should work in v2 or v3 called Out-ConsoleGraph.

Here’s the code, minus, the comment-based help. I’ve commented the quote quite a bit so I won’t spend a lot of time explaining it in detail.

The function requires that PowerShell be running in STA mode, which shouldn’t really be an issue. The intent is that you will be piping objects to the function. You need to specify a property that you want to graph and an object property to use as the label or caption for each object. The default caption is the Name property which seems pretty common. The property you are graphing must have a numeric value. The function’s premise is to get the window width, then write the caption and a graph figure using the remaining available width. The function has a bit of code to calculate the longest caption value so that everything lines up and then determines how much space remains for graphing.

The graph is really more of a proportional representation as opposed to actual value. In short, I find the largest property value which essentially becomes the 100% mark. All other values are calculated as percentages and graphed accordingly. This might be easier to understand if you see it in action.

This is getting all non-Microsoft processes and creating a graph of the WorkingSet property.

out-consolegraph-1

The graph title and color are customizable via parameters. This should work for any type of object as long as you can have a numeric property.

out-consolegraph-2

This command will work in the PowerShell ISE but I think it works better in the PowerShell console. Remember, this command is NOT writing to the pipeline so all you can do is view the output.

Download Out-ConsoleGraph and let me know what you think.

Friday Fun: Another PowerShell Console Graph

Late last year I posted a demo script to create a horizontal bar graph in the PowerShell console. I liked it and many of you did as well. But I also wanted to be able to create a vertical bar graph, ie one with columns. This is much trickier since you have to tell PowerShell exactly where to “paint” the graph.

I’ve posted other articles on using the coordinates in the host and that is what I ended up doing for today’s Friday Fun. This demo script only works in the PowerShell console. It will run in the ISE but you won’t get the desired result. Let me post the code and then I’ll go through a few things.


Param([string]$computername=$env:computername)

Clear-Host

#get the data
$drives=Get-WmiObject -Class Win32_LogicalDisk -Filter "drivetype=3" -computername $computername

#define a set of colors for the graphs
$colors=@("Yellow","Magenta","Green","Cyan","Red")

#set cursor position
$Coordinate = New-Object System.Management.Automation.Host.Coordinates
$Coordinate.X= 10
$Coordinate.Y= [int]($host.ui.rawui.WindowSize.Height -5)

#save starting coordinates
$startY=$Coordinate.Y
$startX=$Coordinate.X

#counter for colors
$c=0

#adjust Y so we can write the caption
$Coordinate.Y+=1

foreach ($drive in $drives) {
#set the color to the first color in the array of colors
$color=$colors[$c]
$legend=$drive.DeviceID
#calculate used space value
$used=$Drive.Size - $Drive.FreeSpace
[int]$usedValue=($used/($drive.size))*10
#adjust for values less than 0 so something gets graphed
if ($usedValue -le 0) {
[int]$usedValue=($used/($drive.size))*50
}

#format usage as a percentage
$usedPer="{0:p2}" -f ($used/($drive.size))
#set the cursor to the new coordinates
$host.ui.rawui.CursorPosition=$Coordinate
#write the caption
write-host $legend -nonew
#move the Y coordinate up to start the graph
$coordinate.Y-=1

for ($i=$usedValue;$i -gt 0;$i--) {
$host.ui.rawui.CursorPosition=$Coordinate
#draw the color space for the graph
write-host " " -BackgroundColor $color -nonewline
#move Y up 1
$coordinate.y--
#repeat until we reach the $usedValue
}
#set new coordinate
$host.ui.rawui.CursorPosition=$Coordinate
#write the usage percentage at the top of the bar
write-host $usedPer -nonewline

#reset Y to where we started + 1
$Coordinate.Y=($startY+1)
#move X to the right
$coordinate.x+=8
#reset coordinates
$host.ui.rawui.CursorPosition=$Coordinate
#increment the color counter
$c++

#repeat for the next drive

} #foreach

#reset coordinates so we can write a legend
$coordinate.Y=$StartY+2
$coordinate.X=$startX
$host.ui.rawui.CursorPosition=$Coordinate
write-host ("Drive Usage for {0}" -f $drives[0].__SERVER)

#move cursor to bottom of the screen and write a blank line
$Coordinate.X=1
$coordinate.Y=[int]($host.ui.rawui.WindowSize.Height-2)
$host.ui.rawui.CursorPosition=$Coordinate
write-host ""

#your PowerShell prompt will now be displayed

This script gets drive usage and creates a vertical bar chart displaying disk utilization. Everyone loves a good drive space report and they always make good demos.

The script creates a System.Management.Automation.Host.Coordinates object, setting the value of X and Y that should be starting in the bottom left corner of the console.


#set cursor position
$Coordinate = New-Object System.Management.Automation.Host.Coordinates
$Coordinate.X= 10
$Coordinate.Y= [int]($host.ui.rawui.WindowSize.Height -5)
#save starting coordinates
$startY=$Coordinate.Y
$startX=$Coordinate.X

I’m also saving these values so I can reset. The script will have to “move” the cursor around the screen to draw the graphs. Once I calculate the values for each drive, I write a blank line using Write-Host with -Backgroundcolor to get the desired graphing effect.


for ($i=$usedValue;$i -gt 0;$i--) {
$host.ui.rawui.CursorPosition=$Coordinate
#draw the color space for the graph
write-host " " -BackgroundColor $color -nonewline
#move Y up 1
$coordinate.y--
#repeat until we reach the $usedValue
}

Notice after each write I move the Y point “up”, until I reach the limit of the current value. I set values as a percentage scaled to 10 so the graph doesn’t end up outside of the buffer. I also made an adjustment for low values that wouldn’t normally trigger a graph so that I get something written to the screen.


#calculate used space value
$used=$Drive.Size - $Drive.FreeSpace
[int]$usedValue=($used/($drive.size))*10
#adjust for values less than 0 so something gets graphed
if ($usedValue -le 0) {
[int]$usedValue=($used/($drive.size))*50
}

After drawing the graph I move the cursor position back to the beginning and write a legend.


#reset coordinates so we can write a legend
$coordinate.Y=$StartY+2
$coordinate.X=$startX
$host.ui.rawui.CursorPosition=$Coordinate
write-host ("Drive Usage for {0}" -f $drives[0].__SERVER)

Here’s the end result.

This script is really just a proof of concept. I haven’t created any functions to simply any of this or make it easy to use with other values. This is also a bit advanced so if you look at this and it makes your head hurt, don’t worry about it. You would only use something like this in special cases. Still, I’d like to know what you think, how it works for you and if you extend it to a more re-usable form.

Download demo-bargraph. The script will default to the local computer, but you can run specify any computer you want.


PS C:\Scripts\> .\demo-bargraph.ps1 Mycomputer

Enjoy and have fun.