For some reason I wanted to write a trace route script in PowerShell, but decided to run it through Google first to see if it had been done. Surprisingly few results came up, and as far as I can tell, only one true PowerShell script doing Trace Route without just being a wrapper for tracert or something similar: https://snoj.us/75/traceroute-with-starting-ttls/

Naturally I wanted to tweak it and give it my personal touch, and here is my result:

function Trace-Route {
<#
.SYNOPSIS
Trace the route between source computer and a target machine.
.DESCRIPTION
Trace the route between source computer and a target machine.
.EXAMPLE
Trace-Route Computer01
Perform trace route to Computer01
.EXAMPLE
Trace-Route -Target http://www.microsoft.com -ResolveHostname
Perform trace route to http://www.microsoft.com and try to resolve hostname for each hop.
Note! This will slow down the function somewhat.
.NOTES
Author: Øyvind Kallstad
Date: 28.10.2014
Version: 1.1
#>
[CmdletBinding()]
param(
# Hostname or IP to trace to.
[Parameter(Position = 0, ValueFromPipeline = $true)]
[string] $Target = $env:COMPUTERNAME,
# Set starting hop.
[Parameter()]
[int] $BeginHop = 1,
# Set maximum number of hops.
[Parameter()]
[int] $MaxHops = 30,
# Define timeout in milliseconds.
[Parameter()]
[int] $Timeout = 1000,
# Try to resolve hostname for IP in each hop.
[Parameter()]
[switch] $ResolveHostname = $false
)
# verify that we can reach target system
try{
$ping = New-Object System.Net.NetworkInformation.Ping
$pingResult = $ping.Send($Target)
if(-not($pingResult.Status -eq 'Success')){
Write-Warning "Unable to resolve target system $Target"
exit
}
}
catch{
Write-Warning "Unable to resolve target system $Target"
exit
}
# define some data to send
$sendBytes = @([byte][char]'a'..[byte][char]'z')
for($i = $BeginHop; $i -lt $MaxHops; $i++) {
# define ping options; set start hop and fragmentation to true
$pingOptions = new-object System.Net.NetworkInformation.PingOptions $i, $true
# perform ping
$pingReply = $ping.Send($Target, $Timeout, $sendBytes, $pingOptions)
# get ip for current hop if possible
if($pingReply.Address -ne $null){
$ip = $pingReply.Address
}
else{
$ip = '*'
}
# get roundtrip time
$roundtripTime = $pingReply.RoundtripTime
# get status
$hopStatus = $pingReply.Status
# resolve hostname
if ($ResolveHostname) {
try{
$resolvedHostname = "[$(([System.Net.Dns]::GetHostEntry($ip)).HostName)]"
}
catch{
$resolvedHostname = ''
}
}
# create custom object and send to pipeline
Write-Output ([PSCustomObject] [Ordered] @{
Hop = $i.ToString()
IP = "$($ip) $($resolvedHostname)"
Status = $hopStatus
RoundtripTime = $roundtripTime
})
# clean up
Remove-Variable ip, roundtripTime, hopStatus, resolvedHostname ErrorAction 'SilentlyContinue'
# stop loop if current ip matches the target ip
if($pingReply.Address -eq $pingResult.Address){break}
}
}

view raw
Trace-Route.ps1
hosted with ❤ by GitHub

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s