Code
Twizzle • 20 Mar 2024 •
Creating little Powershell scripts is quite satisfying. There are always a small number of processes I repeat but have to look up how to do them via a command line each time. So I just use "found code" and ChatGPT to write me a Powershell script so I can keep it for later. For example, I sometimes ping a range of IP addresses. This can be done via a command line:
for /L %i in (1,1,254) do ping -n 1 192.168.1.%i
The only issue with that, is that you have to tweak the IP address manually each time, especially if you only want to only ping from .10 to .20 - its a pain.
My Powershell script prompts for an IP address in CIDR format: 192.168.1.0/24 which then converts it, knowing that the range of IP addresses it needs to ping is 192.168.1.1 to 192.168.1.254
I am not sure how often I will use it, but it is there now just in case.
# calculate IP address range from CIDR notation
# https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing
function cidrToIpRange {
param (
[string] $cidrNotation
)
$addr, $maskLength = $cidrNotation -split '/'
[int]$maskLen = 0
if (-not [int32]::TryParse($maskLength, [ref] $maskLen)) {
throw "Cannot parse CIDR mask length string: '$maskLen'"
}
if (0 -gt $maskLen -or $maskLen -gt 32) {
throw "CIDR mask length must be between 0 and 32"
}
$ipAddr = [Net.IPAddress]::Parse($addr)
if ($ipAddr -eq $null) {
throw "Cannot parse IP address: $addr"
}
if ($ipAddr.AddressFamily -ne [Net.Sockets.AddressFamily]::InterNetwork) {
throw "Can only process CIDR for IPv4"
}
$shiftCnt = 32 - $maskLen
$mask = -bnot ((1 -shl $shiftCnt) - 1)
$ipNum = [Net.IPAddress]::NetworkToHostOrder([BitConverter]::ToInt32($ipAddr.GetAddressBytes(), 0))
$ipStart = ($ipNum -band $mask) + 1
$ipEnd = ($ipNum -bor (-bnot $mask)) - 1
# return as tuple of strings:
([BitConverter]::GetBytes([Net.IPAddress]::HostToNetworkOrder($ipStart)) | ForEach-Object { $_ } ) -join '.'
([BitConverter]::GetBytes([Net.IPAddress]::HostToNetworkOrder($ipEnd)) | ForEach-Object { $_ } ) -join '.'
}
$ipToUse = Read-Host "Enter IP address and subnet mask (e.g., 192.168.1.0/24):"
$start, $end = cidrToIpRange $ipToUse
Write-Host "Start: $start, end: $end"
# Function to convert IP address to integer
function ConvertTo-Int32 {
param (
[string]$IPAddress
)
$ipBytes = $IPAddress.Split('.')
$intIP = 0
for ($i = 0; $i -lt 4; $i++) {
$intIP += [int]$ipBytes[$i] * [math]::Pow(256, 3 - $i)
}
return $intIP
}
# Function to convert integer to IP address
function ConvertTo-IPAddress {
param (
[int]$IntIP
)
$ipBytes = @()
for ($i = 0; $i -lt 4; $i++) {
$ipBytes += [math]::Floor($IntIP / [math]::Pow(256, 3 - $i))
$IntIP = $IntIP % [math]::Pow(256, 3 - $i)
}
return $ipBytes -join '.'
}
# Function to get IP range
function Get-IPRange {
param (
[string]$StartIPAddress,
[string]$EndIPAddress
)
$startInt = ConvertTo-Int32 -IPAddress $StartIPAddress
$endInt = ConvertTo-Int32 -IPAddress $EndIPAddress
$IPRange = @()
for ($i = $startInt; $i -le $endInt; $i++) {
$IPRange += ConvertTo-IPAddress -IntIP $i
}
return $IPRange
}
# Prompt for IP address range
$startIP = $start
$endIP = $end
# Get IP address range
$ipRange = Get-IPRange -StartIPAddress $startIP -EndIPAddress $endIP
# Ping each IP address in the range
foreach ($ip in $ipRange) {
$pingResult = Test-Connection -ComputerName $ip -Count 1 -Quiet
if ($pingResult) {
Write-Host "Ping successful: $ip"
}
}