I think one of the best ways to learn PowerShell is by using it. I’ve often found the best way to use it is to find a project to work on. With that in mind, I’m going to start us on a little PowerShell project. Although the end result will most likely be useful, the journey is more important than the destination.
I’m hoping that as you read the articles in this short series, you’ll learn new PowerShell commands, techniques and concepts. Honestly, I’m not sure where we’ll end up. I know where I want to start and what I want to show you, but I expect that over the course of working on this project, I’ll come up with another idea or concept to add on.
This is the way I work: start with a core concept and get it working, then slowly add additional features. Even if I know in advance everything that I want to include, I rarely create a tool with everything from the very beginning. The more complex the project, then the more likely the need to debug and troubleshoot. I find it easier to take an iterative approach getting each step to work before adding the next. But enough philosophy, let’s get scripting.
PowerShell Ping Sweep Tool Article Series
The task is to create a PowerShell tool that can be used to ping a range of IP addresses. Eventually we should end up with a function that we can run just like a cmdlet. But we don’t need to do that just yet. First, I always get the core commands to work at an interactive console prompt. Because there is no difference between commands running in the console versus a script, let’s get the basics sorted out first without the distractions of trying to create a function.
I know that the PowerShell command for the actual pinging will be Test-Connection. I’ll trust that at some point you will look at full help and examples for this command. The cmdlet will take a computername or IP address and ping it.
In looking at the help, I see a –Quiet parameter. When used, the cmdlet will return either True or False depending on whether there was a response or not.
By default, Test-Connection sends four pings. Since I’m testing a local subnet, if the computer doesn’t respond to a single ping, it probably isn’t going to respond to any, so I can improve performance by using the –Count parameter.
Next, I need to figure out how to ping a range of addresses such as 172.16.30.200 to 172.16.30.250. I certainly don't want to type all those addresses. There are a few ways to solve this. Here's the first:
In this example, I'm using a looping construct that says, "While the value of $a is less than or equal to the value of $z, create a string that looks like an IP address using the current value of $a and then increment $a by 1." All I have to do is insert my Test-Connection command:
And here is an alternative:
In this example, I am getting all of the numbers between $a and $z using the Range (..) operator. Each value is piped to ForEach-Object, where I am constructing the IP address by using the –Replace operator. The operator's parameters are a regular expression pattern to match and the value to replace on that match. The pattern is looking for an ending in 0, and it will be replaced with some number between $a and $z. So which is better? On one hand, I would say whichever you find easier to understand. But perhaps some hard data would help. Taking Test-Connection out of the picture, which technique is faster at creating an IP address? To figure this out, we can use Measure-Command. To use this cmdlet, simply wrap the commands to be tested in a set of curly braces to create a scriptblock.
Pretty darn fast. Let's check the other technique.
When using Measure-Command, first make sure the scriptblock runs successfully. As you can see, the first technique is significantly faster at least from the computer's perspective. Personally, there's not much human difference between the two. But you may want to run a few tests and average the results to be sure.
This command is looping 10 times and measuring the scriptblock each time through. The results are then piped to Measure-Object to calculate the average. Changing the scriptblock to use the other code I get this result. Ok. I'll go with the first option. At this point I can start scripting something to test my logic and lay the foundation for an advanced function.
I've added a Write-Host line to see what IP address is being tested and to verify my code that defines the variable. I run the script from the console: Success! Eventually the variables in my script will most likely become function parameters, but I get ahead of myself. For now, I have a rudimentary PowerShell script that pings a range of IP addresses and tells me if they can be pinged or not. Obviously we are far from finished, so I hope you'll watch for the next article and come back for the next steps in our journey.