I thought I would do some-ping awesome!
#Pro-Pingv3
# Set the log file path
$Logfile = ".\ping.log"
# Define the logging function
function Log-Output {
param (
[Parameter(Mandatory=$true, ValueFromPipeline=$true)]
[string]$Message
)
$timestamp = Get-Date -Format "yyyy-MM-dd.HH:mm:ss"
"$timestamp $Message" | Out-File -Append -FilePath $Logfile
}
# Get all active network connections
$connections = Get-NetTCPConnection | Where-Object { $_.State -eq "Established" }
# Create an empty array to store the results
$results = @()
# Iterate through each active connection
foreach ($connection in $connections) {
# Get the process ID (PID) associated with the connection
$processId = $connection.OwningProcess
# Get the process information based on the PID
$process = Get-Process -Id $processId -ErrorAction SilentlyContinue
# Create a custom object to store the connection details
$result = [PSCustomObject]@{
LocalAddress = $connection.LocalAddress
LocalPort = $connection.LocalPort
RemoteAddress = $connection.RemoteAddress
RemotePort = $connection.RemotePort
State = $connection.State
ProcessName = $process.ProcessName
ProcessId = $processId
}
# Add the custom object to the results array
$results += $result
}
# Group the results by process name and get the unique remote IP addresses for each process
$processGroups = $results | Group-Object -Property ProcessName | ForEach-Object {
$processName = $_.Name
$processIpAddresses = $_.Group |
Select-Object -ExpandProperty RemoteAddress |
Where-Object { $_ -ne "127.0.0.1" -and $_ -ne "::1" } |
Select-Object -Unique
[PSCustomObject]@{
ProcessName = $processName
IPAddresses = $processIpAddresses
}
}
# Display the numbered list of processes with their associated IP addresses
Write-Host "Select a process to analyze:"
for ($i = 0; $i -lt $processGroups.Count; $i++) {
$processName = $processGroups[$i].ProcessName
$ipAddresses = $processGroups[$i].IPAddresses -join ", "
Write-Host "$($i + 1). $processName ($ipAddresses)"
}
# Log the process list to the file
"Process List:" | Log-Output
for ($i = 0; $i -lt $processGroups.Count; $i++) {
$processName = $processGroups[$i].ProcessName
$ipAddresses = $processGroups[$i].IPAddresses -join ", "
"$($i + 1). $processName ($ipAddresses)" | Log-Output
}
# Prompt the user to enter the number of the process they want to analyze
$selectedProcessIndex = Read-Host "Enter the number of the process"
# Validate the user's input
while ([int]$selectedProcessIndex -lt 1 -or [int]$selectedProcessIndex -gt $processGroups.Count) {
Write-Host "Invalid selection. Please enter a valid number."
$selectedProcessIndex = Read-Host "Enter the number of the process"
}
# Get the selected process name and IP addresses
$selectedProcessName = $processGroups[$selectedProcessIndex - 1].ProcessName
$selectedProcessIpAddresses = $processGroups[$selectedProcessIndex - 1].IPAddresses
# Confirm the user's selection
Write-Host "You selected: $selectedProcessName"
$confirmation = Read-Host "Do you want to proceed with this process? (Y/N) [Y]"
# Validate the user's confirmation
while ($confirmation -ne "" -and $confirmation -ne "Y" -and $confirmation -ne "N") {
Write-Host "Invalid input. Please enter 'Y' or 'N' (default is 'Y')."
$confirmation = Read-Host "Do you want to proceed with this process? (Y/N) [Y]"
}
if ($confirmation -eq "N") {
Write-Host "Process selection canceled. Exiting script."
exit
}
# Display the IP addresses associated with the selected process
Write-Host ""
Write-Host "The IP Addresses associated with the process $selectedProcessName are:"
foreach ($ipAddress in $selectedProcessIpAddresses) {
Write-Host $ipAddress
}
Write-Host ""
# Log the selected process and its IP addresses to the file
"Selected Process: $selectedProcessName" | Log-Output
"IP Addresses:" | Log-Output
foreach ($ipAddress in $selectedProcessIpAddresses) {
$ipAddress | Log-Output
}
# Function to perform fast traceroute and return the output
function Get-FastTraceroute {
param (
[Parameter(Mandatory=$true)]
[string]$traceDestination,
[int]$waitTime = 100,
[int]$maxTTL = 30
)
$resultTable = @()
for ($ttl = 1; $ttl -le $maxTTL; $ttl++) {
$pingOutput = & ping -n 1 -i $ttl -w $waitTime $traceDestination
$expiredLine = $pingOutput | Select-String -Pattern "TTL expired"
if ($expiredLine -ne $null) {
$expiredIP = $expiredLine.ToString().Split(" ")[2].TrimEnd(":")
$resultTable += [PSCustomObject]@{
TTL = $ttl
ExpiredIP = $expiredIP
}
}
}
$reachable = Test-Connection -ComputerName $traceDestination -Count 1 -Quiet
return [PSCustomObject]@{
TraceDestination = $traceDestination
PingResults = $resultTable
Reachable = $reachable
}
}
# Create an empty array to store the traceroute results
$tracerouteResults = @()
# Perform traceroute for each IP address related to the selected process
foreach ($ipAddress in $selectedProcessIpAddresses) {
Write-Host "Starting traceroute for IP address: $ipAddress"
$traceroute = Get-FastTraceroute -traceDestination $ipAddress
$tracerouteResults += [PSCustomObject]@{
IPAddress = $ipAddress
Traceroute = $traceroute.PingResults
}
# Log the traceroute results to the file
"Traceroute for IP Address: $ipAddress" | Log-Output
foreach ($hop in $traceroute.PingResults) {
"TTL: $($hop.TTL), Expired IP: $($hop.ExpiredIP)" | Log-Output
}
}
# Sort the traceroute results based on the number of hops (smallest to largest)
$tracerouteResults = $tracerouteResults | Sort-Object -Property { $_.Traceroute.Count }
# Create the tree structure
$tree = @{}
foreach ($result in $tracerouteResults) {
$ipAddress = $result.IPAddress
$traceroute = $result.Traceroute
$currentNode = $tree
foreach ($hop in $traceroute) {
$hopIP = $hop.ExpiredIP
if ($currentNode.ContainsKey($hopIP)) {
$currentNode = $currentNode[$hopIP]
}
else {
$currentNode[$hopIP] = @{}
$currentNode = $currentNode[$hopIP]
}
}
$currentNode[$ipAddress] = $null
}
# Generate the tree output
function Generate-TreeOutput($node, $depth, $prefix) {
$output = ""
$lastIndex = $node.Keys.Count - 1
foreach ($key in $node.Keys) {
$isLast = $node.Keys.IndexOf($key) -eq $lastIndex
$line = $prefix + $(if ($isLast) { "└─" } else { "├─" }) + $key
$output += $line + "`n"
if ($node[$key] -ne $null) {
$childPrefix = $prefix + $(if ($isLast) { " " } else { "│ " })
$output += Generate-TreeOutput $node[$key] ($depth + 1) $childPrefix
}
}
return $output
}
$treeOutput = Generate-TreeOutput $tree 0 ""
# Display the tree output
Write-Host "Traceroute Tree:"
Write-Host $treeOutput
# Log the traceroute tree to the file
"Traceroute Tree:" | Log-Output
$treeOutput | Log-Output
# Get the 1st, 2nd, and last responding IP addresses from the traceroute results
$pingIpAddresses = @()
$pingIpAddresses += $tracerouteResults[0].Traceroute | Select-Object -First 1 | Select-Object -ExpandProperty ExpiredIP
$pingIpAddresses += $tracerouteResults[0].Traceroute | Select-Object -Skip 1 | Select-Object -First 1 | Select-Object -ExpandProperty ExpiredIP
$pingIpAddresses += $tracerouteResults | ForEach-Object { $_.Traceroute | Select-Object -Last 1 | Select-Object -ExpandProperty ExpiredIP } | Select-Object -Last 1
# Check if there are any responding IP addresses
if ($pingIpAddresses -contains $null) {
Write-Host "No responding IP addresses found for the selected process. Exiting script."
exit
}
# Set the maximum response time for padding
$maxResponseTime = 25
function Ping-And-Display {
while ($true) {
$outputs = @()
foreach ($ipAddress in $pingIpAddresses) {
# Send a single ping to the IP address
$pingResult = Test-Connection -ComputerName $ipAddress -Count 1 -ErrorAction SilentlyContinue
if ($pingResult) {
# Check if the response time is 0ms
if ($pingResult.ResponseTime -eq 0) {
$line = "0"
}
elseif ($pingResult.ResponseTime -le $maxResponseTime) {
# Generate a string of 'X's equal to the response time
$line = 'X' * $pingResult.ResponseTime
}
else {
# Display the response time if it exceeds the maximum
$line = $pingResult.ResponseTime.ToString()
}
# Pad the line to align the columns
$paddedLine = $line.PadRight($maxResponseTime)
# Prepend the IP address
$output = "$ipAddress $paddedLine"
}
else {
# If ping fails, generate a line of dashes equal to the maximum response time
$output = "$ipAddress " + ('-' * $maxResponseTime)
}
# Add the output to the array
$outputs += $output
}
# Join the outputs with a separator
$combinedOutput = $outputs -join " | "
# Output the combined line to the screen
Write-Output $combinedOutput
# Log the combined output to the file
$combinedOutput | Log-Output
# Wait for 1 second before the next ping
Start-Sleep -Seconds 1
}
}
# Start the ping and display process
Ping-And-Display
TreePing my balls off
#TreePing has issues
# Set the log file path
$Logfile = ".\ping.log"
# Define the logging function
function Log-Output {
param (
[Parameter(Mandatory=$true, ValueFromPipeline=$true)]
[string]$Message
)
$timestamp = Get-Date -Format "yyyy-MM-dd.HH:mm:ss"
"$timestamp $Message" | Out-File -Append -FilePath $Logfile
}
# Get all active network connections
$connections = Get-NetTCPConnection | Where-Object { $_.State -eq "Established" }
# Create an empty array to store the results
$results = @()
# Iterate through each active connection
foreach ($connection in $connections) {
# Get the process ID (PID) associated with the connection
$processId = $connection.OwningProcess
# Get the process information based on the PID
$process = Get-Process -Id $processId -ErrorAction SilentlyContinue
# Create a custom object to store the connection details
$result = [PSCustomObject]@{
LocalAddress = $connection.LocalAddress
LocalPort = $connection.LocalPort
RemoteAddress = $connection.RemoteAddress
RemotePort = $connection.RemotePort
State = $connection.State
ProcessName = $process.ProcessName
ProcessId = $processId
}
# Add the custom object to the results array
$results += $result
}
# Group the results by process name and get the unique remote IP addresses for each process
$processGroups = $results | Group-Object -Property ProcessName | ForEach-Object {
$processName = $_.Name
$processIpAddresses = $_.Group |
Select-Object -ExpandProperty RemoteAddress |
Where-Object { $_ -ne "127.0.0.1" -and $_ -ne "::1" } |
Select-Object -Unique
[PSCustomObject]@{
ProcessName = $processName
IPAddresses = $processIpAddresses
}
}
# Display the numbered list of processes with their associated IP addresses
Write-Host "Select a process to analyze:"
for ($i = 0; $i -lt $processGroups.Count; $i++) {
$processName = $processGroups[$i].ProcessName
$ipAddresses = $processGroups[$i].IPAddresses -join ", "
Write-Host "$($i + 1). $processName ($ipAddresses)"
}
# Log the process list to the file
"Process List:" | Log-Output
for ($i = 0; $i -lt $processGroups.Count; $i++) {
$processName = $processGroups[$i].ProcessName
$ipAddresses = $processGroups[$i].IPAddresses -join ", "
"$($i + 1). $processName ($ipAddresses)" | Log-Output
}
# Prompt the user to enter the number of the process they want to analyze
$selectedProcessIndex = Read-Host "Enter the number of the process"
# Validate the user's input
while ([int]$selectedProcessIndex -lt 1 -or [int]$selectedProcessIndex -gt $processGroups.Count) {
Write-Host "Invalid selection. Please enter a valid number."
$selectedProcessIndex = Read-Host "Enter the number of the process"
}
# Get the selected process name and IP addresses
$selectedProcessName = $processGroups[$selectedProcessIndex - 1].ProcessName
$selectedProcessIpAddresses = $processGroups[$selectedProcessIndex - 1].IPAddresses
# Confirm the user's selection
Write-Host "You selected: $selectedProcessName"
$confirmation = Read-Host "Do you want to proceed with this process? (Y/N) [Y]"
# Validate the user's confirmation
while ($confirmation -ne "" -and $confirmation -ne "Y" -and $confirmation -ne "N") {
Write-Host "Invalid input. Please enter 'Y' or 'N' (default is 'Y')."
$confirmation = Read-Host "Do you want to proceed with this process? (Y/N) [Y]"
}
if ($confirmation -eq "N") {
Write-Host "Process selection canceled. Exiting script."
exit
}
# Display the IP addresses associated with the selected process
Write-Host ""
Write-Host "The IP Addresses associated with the process $selectedProcessName are:"
foreach ($ipAddress in $selectedProcessIpAddresses) {
Write-Host $ipAddress
}
Write-Host ""
# Log the selected process and its IP addresses to the file
"Selected Process: $selectedProcessName" | Log-Output
"IP Addresses:" | Log-Output
foreach ($ipAddress in $selectedProcessIpAddresses) {
$ipAddress | Log-Output
}
# Function to perform fast traceroute and return the output
function Get-FastTraceroute {
param (
[Parameter(Mandatory=$true)]
[string]$traceDestination,
[int]$waitTime = 100,
[int]$maxTTL = 30
)
$resultTable = @()
for ($ttl = 1; $ttl -le $maxTTL; $ttl++) {
$pingOutput = & ping -n 1 -i $ttl -w $waitTime $traceDestination
$expiredLine = $pingOutput | Select-String -Pattern "TTL expired"
if ($expiredLine -ne $null) {
$expiredIP = $expiredLine.ToString().Split(" ")[2].TrimEnd(":")
$resultTable += [PSCustomObject]@{
TTL = $ttl
ExpiredIP = $expiredIP
}
}
}
$reachable = Test-Connection -ComputerName $traceDestination -Count 1 -Quiet
return [PSCustomObject]@{
TraceDestination = $traceDestination
PingResults = $resultTable
Reachable = $reachable
}
}
# Create an empty array to store the traceroute results
$tracerouteResults = @()
# Perform traceroute for each IP address related to the selected process
foreach ($ipAddress in $selectedProcessIpAddresses) {
Write-Host "Starting traceroute for IP address: $ipAddress"
$traceroute = Get-FastTraceroute -traceDestination $ipAddress
$tracerouteResults += [PSCustomObject]@{
IPAddress = $ipAddress
Traceroute = $traceroute.PingResults
}
# Log the traceroute results to the file
"Traceroute for IP Address: $ipAddress" | Log-Output
foreach ($hop in $traceroute.PingResults) {
"TTL: $($hop.TTL), Expired IP: $($hop.ExpiredIP)" | Log-Output
}
}
# Sort the traceroute results based on the number of hops (smallest to largest)
$tracerouteResults = $tracerouteResults | Sort-Object -Property { $_.Traceroute.Count }
# Create the tree structure
$tree = @{}
foreach ($result in $tracerouteResults) {
$ipAddress = $result.IPAddress
$traceroute = $result.Traceroute
$currentNode = $tree
foreach ($hop in $traceroute) {
$hopIP = $hop.ExpiredIP
if ($currentNode.ContainsKey($hopIP)) {
$currentNode = $currentNode[$hopIP]
}
else {
$currentNode[$hopIP] = @{}
$currentNode = $currentNode[$hopIP]
}
}
$currentNode[$ipAddress] = $null
}
# Generate the tree output with ping responses
function Generate-TreeOutput($node, $depth, $prefix) {
$output = ""
$lastIndex = $node.Keys.Count - 1
foreach ($key in $node.Keys) {
$isLast = $node.Keys.IndexOf($key) -eq $lastIndex
# Send a single ping to the IP address
$pingResult = Test-Connection -ComputerName $key -Count 1 -ErrorAction SilentlyContinue
if ($pingResult) {
# Check if the response time is 0ms
if ($pingResult.ResponseTime -eq 0) {
$pingResponse = "0"
}
elseif ($pingResult.ResponseTime -le 25) {
# Generate a string of 'X's equal to the response time
$pingResponse = 'X' * $pingResult.ResponseTime
}
else {
# Display the response time if it exceeds 25ms
$pingResponse = $pingResult.ResponseTime.ToString()
}
}
else {
# If ping fails, generate a string of dashes
$pingResponse = "-" * 10
}
$line = $prefix + $(if ($isLast) { "└─" } else { "├─" }) + "$key $pingResponse"
$output += $line + "`n"
if ($node[$key] -ne $null) {
$childPrefix = $prefix + $(if ($isLast) { " " } else { "│ " })
$output += Generate-TreeOutput $node[$key] ($depth + 1) $childPrefix
}
}
return $output
}
# Function to continuously ping and display the traceroute tree
function Ping-And-Display {
$previousTreeOutput = ""
while ($true) {
# Generate the tree output with ping responses
$treeOutput = Generate-TreeOutput $tree 0 ""
# Clear the screen only if the tree output has changed
if ($treeOutput -ne $previousTreeOutput) {
Clear-Host
# Display the tree output
Write-Host "Traceroute Tree:" -NoNewline
Write-Host "`r$treeOutput" -NoNewline
# Log the traceroute tree to the file
"Traceroute Tree:" | Log-Output
$treeOutput | Log-Output
$previousTreeOutput = $treeOutput
}
# Wait for 1 second before the next ping
Start-Sleep -Seconds 1
}
}
# Start the ping and display process
Ping-And-Display