Earlier today, I had an opportunity to help a coworker run ICMP requests against a series of IP addresses. They were being pulled in from a CSV file, which contained hostnames with matching IP addresses. If for some reason the import failed, such as the file wasn’t where it was supposed to be, he wanted to supply a single IP address he knew would fail in place of the successful CSV import. I suspect this was for testing purposes. Whatever the reason, I obliged him in his quest and request. I leaned heavily on a recently written and published article of mine: Hash Table to CSV, Revisited. It lined up perfectly with what I was working toward in this instance.
The goal here was to fake out an upcoming Foreach loop in such a way that no coding changes needed to be made, whether or not the CSV file existed, etc. That was the end goal for this work: leave the later code doing what it had been doing previously.
We’re, mostly, going to start with the code. In this first example, you’ll have to believe me that the file IPs.csv does in fact exist, and it contains two columns. One is the hostname, which we don’t actually even use in this example, and the other is the IP address. As expected, this column contains a properly formatted IP address. As everything is in place, the CSV file is imported and saved in $IPAddresses. Following that, the code loops through the contents of our new variable. For every entry, it returns True or False depending on whether it’s able to return a successful ping request or not, against that IP address.
try { $IPAddresses = Import-Csv -Path 'C:\IPs.csv' } catch { $IPAddresses = [PSCustomObject]@{Host = 'Test';IP = '8.8.8.9'} } # End try-catch Foreach ($IP in $IPAddresses) { If (Test-Connection $IP.IP -Count 1 -Quiet) { $true } Else { $false } # End If-Else. } # End Foreach. Pinging 8.8.8.8 [8.8.8.8] with 32 bytes of data: Reply from 8.8.8.8: bytes=32 time=13ms TTL=50 Ping complete. True Pinging 216.58.193.206 [216.58.193.206] with 32 bytes of data: Reply from 216.58.193.206: bytes=32 time=12ms TTL=53 Ping complete. True
In this next example, we’ve altered the CSV file extension. This attempted CSV import will fail, and will therefore execute our code in the catch block. This will make it appear as though we’ve imported the CSV; however, because we recognize this IP address and its guaranteed to fail, we’ll know there was a problem with the CSV import.
try { $IPAddresses = Import-Csv -Path 'C:\IPs.csvvvvvv' } catch { $IPAddresses = [PSCustomObject]@{Host = 'Test';IP = '8.8.8.9'} } # End try-catch Foreach ($IP in $IPAddresses) { If (Test-Connection $IP.IP -Count 1 -Quiet) { $true } Else { $false } # End If-Else. } # End Foreach. Pinging 8.8.8.9 [8.8.8.9] with 32 bytes of data: Request timed out. Ping complete. False
There are other ways to handle this, yes. But remember, the co-worker needed data to be produced just as it would be if it worked (the import part), even though it didn’t. It had something to do with JSON, schemas, and Azure Log Analytics. It was good enough for him, so it was good enough for me, too.