- Create a certificate-signed RDP shortcut via Group Policy - Fri, Aug 9 2019
- Monitor web server uptime with a PowerShell script - Tue, Aug 6 2019
- How to build a PowerShell inventory script for Windows Servers - Fri, Aug 2 2019
Peter Drucker, a legendary management consultant, is quoted as saying, “You can't manage what you can't measure." This quote deals with managing work processes from a company-management perspective but nonetheless applies to lots of activities.
In our IT pro world, we come across problems that require all kinds of measurement every day. Perhaps one day it's building a summary report from a CSV file, checking how many servers we successfully patched the night before, or how many widgets our company sold last week.
There are lots of free and paid tools out there that allow you to perform all kinds of measurements and calculations. But nearly all are overkill if you just want to check quickly how many tables are in a database. For these simple examples and times when you need to perform any kind of calculation in your PowerShell scripts, you've got the Measure-Object command available.
Measure-Object can provide five different numbers given a set of data: Count, Average, Sum, Minimum, and Maximum. These labels are self-explanatory, but how to feed data into Measure-Object isn't necessarily so.
Measure-Object accepts pipeline input, and this is where you'll see this command used in the more frequent contexts. The values passed to it determine how it calculates its figures.
For example, let's just take a simple case like a string or an integer and pipe that to Measure-Object.
Notice that it doesn't care what kind of input it gets. It's just counting the number of objects passed to it and displays the total count. We could generate ten different objects at once in an array and pass those to it, and we'd get the same result.
PS> 0..10 | Measure-Object Count : 11 Average : Sum : Maximum : Minimum : Property :
While we're here, we can also populate the other values Measure-Object can calculate by specifying them as parameters. Note that we can only gather these numbers from integers. Using strings in this case will result in an error.
PS> 0..10 | Measure-Object -Sum -Average -Maximum -Minimum Count : 11 Average : 5 Sum : 55 Maximum : 10 Minimum : 0 Property :
How about reading a CSV file of employees and how many widgets they built?
$employees = '"Employee","Date","WidgetsBuilt" "Adam","1/4/15","531" "Adam","1/5/15","53" "Joe","1/6/15","436" "Joe","1/7/15","623"' | ConvertFrom-Csv
We try to get the average number each worker built but immediately run into a problem.
PS> $employees | Measure-Object -Average Measure-Object : Input object "" is not numeric. At line:1 char:14 + $employees | Measure-Object -Average + ~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidType: (:PSCustomObject) [Measure-Object], PSInvalidOperationException + FullyQualifiedErrorId : NonNumericInputObject,Microsoft.PowerShell.Commands.MeasureObjectCommand
The CSV has multiple properties, and Measure-Object doesn't know which one to use. For this instance, we need to use the Property parameter to tell Measure-Command we'd like to average the WidgetsBuilt column.
PS> $employees | Measure-Object -Average -Property WidgetsBuilt Count : 4 Average : 410.75 Sum : Maximum : Minimum : Property : WidgetsBuilt
Measure-Object can receive any set of data and provide average, sum, maximum, and minimum values for numbers and a count value for all types of objects.
For one last example, Measure-Object is also great at calculating numbers involving files as well. Below I know that my C:\Windows folder has 28 files with the biggest one being around 268 kB.
PS> Get-ChildItem -Path C:\Windows | Measure-Object -Property Length ‑Sum ‑Average -Maximum -Minimum Count : 28 Average : 267158.821428571 Sum : 7480447 Maximum : 4847928 Minimum : 0 Property : Length
It doesn't matter what the data set is. As long as each object has an integer property attached to it, Measure-Object can summarize any set of data you throw at it.
my csv file has a header. I use this but I get an error: Measure-Object : Input object “DirectorySize” is not numeric.
$data = Import-Csv -Delimiter ‘,’ -Path $path -Header ‘Path’,’CurrentFileCount’,’CurrentFileSize’,’FileCount’,’DirectoryCount’,’DirectorySize’
How can I skip the first header line?
Found it…
$data = Import-Csv -Delimiter ‘,’ -Path $csvFile
$totalSize = ($data | Measure-Object ‘DirectorySize’ -Sum).Sum
Sorry to bother!