PowerShell Scripts

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