Prof. Powershell
The PowerShell Blacksmith Part 1: Forging the Basic Weapons
In the first part of this' six-part series, Jeff shows you how to use PowerShell from the console.
- By Jeffery Hicks
- 09/24/2013
Way, way, way back in the day, if you needed a tool or a weapon you had to visit your local blacksmith and strike a deal. Hopefully you had a chicken or two or a small bag of gold coins. If you wanted to take a go at hammering out your own tool, you certainly could. But not everyone could do it. Jump to today and for IT Pros, the tools they need are software-based. I am assuming you need tools to manage your servers, users and network resources. More and more these tools are being built out of PowerShell.
Fortunately, you don't have to rely on the village PowerShell professional. With a little experience and perhaps some mentoring from a kindly wizard, you too can build your own tools. I'm not saying you can build a 5-foot broadsword forged from Valyrian steel with a jewel-encrusted hilt as your first project. But if you stick to it, you should be able to craft a useful hand axe for clearing out those pesky server problems. Let's put on our smithy apron and get started.
The most important step in building a PowerShell tool is that you understand how to use PowerShell interacvely from the console. tiYou have to understand cmdlets, the pipeline, variables, arrays, hash tables and basic operators. If you can't put together basic pipelined expressions, you will have a very difficult time tool making. If you are still learning PowerShell or want to get started, I recommend grabbing a copy of Learn Windows PowerShell 3 in a Month of Lunches. Or you can look at the training videos I've done for TrainSignal.
The tool I'm going to walk through may not be the most compelling but watch for techniques and concepts. We're going to look at a few ways of building a PowerShell solution. My challenge is that when using Measure-Object, I'd like a bit more information. For example, I'd like to get the Median value as well as the Average. I'd also like to get the range, that is, the difference between the smallest and largest values. I also get tired of formatting sum values into KB, MB or GB. There has to be a better way.
We'll start with figuring out a solution from the prompt. Here's a variable with some data. Eventually this might be values from file sizes or process virtual memory values.
PS C:\> $a = 1,5,2,6,6,7,3,9,10,8,4
To find the median, we need to find the value where 50 percent of the numbers of less than it and 50 percent are more than it. This may not be the same as the average which is the sum of all the numbers divided by the total number. We can get that with Measure-Object.
PS C:\> $a | measure-object -Average
Count : 11
Average : 5.54545454545455
Sum :
Maximum :
Minimum :
Property :
The next step is to sort the numbers.
PS C:\> $sorted = $a | sort
If $a.count is an odd number, we need to find the middle number where half the numbers are below it and half are above it. The best approach seems to be to add 1 to the count and divide by 2. This value would represent the X number in the list. But arrays count starting at 0, so we'll need to subtract one. Here's the corresponding PowerShell:
PS C:\> $x = (($sorted.count+1)/2)-1
PS C:\> $x
5
Here's the sorted list:
PS C:\> $sorted -join ","
1,2,3,4,5,6,6,7,8,9,10
Which means the median value is $sorted[$x]:
PS C:\> $sorted[$x]
6
If you count, you'll see there are five numbers lower than the first 6 in the list and six above. If the sorted count is an even number, then we need to get the two middle numbers and calculate their average. We need a new number set.
PS C:\> $a = 4,7,1,2
PS C:\> $sorted = $a | sort
To find the middle two numbers we need to know where the middle is.
PS C:\> $i = $sorted.count/2
PS C:\> $i
2
Remember we start counting at 0 so the first number is $i -1.
PS C:\> $x = $sorted[$i-1]
PS C:\> $x
2
And the second number is that many numbers back from the end.
PS C:\> $y = $sorted[-$i]
PS C:\> $y
4
The median will be average of these two numbers.
PS C:\> ($x+$y)/2
3
Which is a bit different than the average.
PS C:\> $a | measure-object -average | select -expand average
3.5
The last bit of information I wanted was the range. Since the numbers are sorted, all we need to do is subtract the smallest from the largest.
PS C:\> $sorted[-1] - $sorted[0]
6
I realize this seemed like a lot of work, but the point is you have to be able to do "it," whatever it is from the console. Using small sample sets of comparable data is a good place to start. If my ultimate goal is to apply these techniques to say file sizes. I don't want to start with Get-ChildItem and at the same time try to figure out the math. Break things apart into components. But now that we have some working examples, we can begin forging a tool. That's for next time. I believe I'm wanted at the tavern.
About the Author
Jeffery Hicks is an IT veteran with over 25 years of experience, much of it spent as an IT infrastructure consultant specializing in Microsoft server technologies with an emphasis in automation and efficiency. He is a multi-year recipient of the Microsoft MVP Award in Windows PowerShell. He works today as an independent author, trainer and consultant. Jeff has written for numerous online sites and print publications, is a contributing editor at Petri.com, and a frequent speaker at technology conferences and user groups.