{"id":50,"date":"2024-05-15T03:10:01","date_gmt":"2024-05-15T03:10:01","guid":{"rendered":"https:\/\/www.scothargan.com\/?page_id=50"},"modified":"2024-05-15T03:10:01","modified_gmt":"2024-05-15T03:10:01","slug":"powershell-scripts","status":"publish","type":"page","link":"https:\/\/www.scothargan.com\/?page_id=50","title":{"rendered":"PowerShell Scripts"},"content":{"rendered":"\n<p>I thought I would do some-ping awesome!<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#Pro-Pingv3\n# Set the log file path\n$Logfile = \".\\ping.log\"\n\n# Define the logging function\nfunction Log-Output {\n    param (\n        &#91;Parameter(Mandatory=$true, ValueFromPipeline=$true)]\n        &#91;string]$Message\n    )\n\n    $timestamp = Get-Date -Format \"yyyy-MM-dd.HH:mm:ss\"\n    \"$timestamp $Message\" | Out-File -Append -FilePath $Logfile\n}\n\n# Get all active network connections\n$connections = Get-NetTCPConnection | Where-Object { $_.State -eq \"Established\" }\n\n# Create an empty array to store the results\n$results = @()\n\n# Iterate through each active connection\nforeach ($connection in $connections) {\n    # Get the process ID (PID) associated with the connection\n    $processId = $connection.OwningProcess\n\n    # Get the process information based on the PID\n    $process = Get-Process -Id $processId -ErrorAction SilentlyContinue\n\n    # Create a custom object to store the connection details\n    $result = &#91;PSCustomObject]@{\n        LocalAddress  = $connection.LocalAddress\n        LocalPort     = $connection.LocalPort\n        RemoteAddress = $connection.RemoteAddress\n        RemotePort    = $connection.RemotePort\n        State         = $connection.State\n        ProcessName   = $process.ProcessName\n        ProcessId     = $processId\n    }\n\n    # Add the custom object to the results array\n    $results += $result\n}\n\n# Group the results by process name and get the unique remote IP addresses for each process\n$processGroups = $results | Group-Object -Property ProcessName | ForEach-Object {\n    $processName = $_.Name\n    $processIpAddresses = $_.Group |\n        Select-Object -ExpandProperty RemoteAddress |\n        Where-Object { $_ -ne \"127.0.0.1\" -and $_ -ne \"::1\" } |\n        Select-Object -Unique\n\n    &#91;PSCustomObject]@{\n        ProcessName = $processName\n        IPAddresses = $processIpAddresses\n    }\n}\n\n# Display the numbered list of processes with their associated IP addresses\nWrite-Host \"Select a process to analyze:\"\nfor ($i = 0; $i -lt $processGroups.Count; $i++) {\n    $processName = $processGroups&#91;$i].ProcessName\n    $ipAddresses = $processGroups&#91;$i].IPAddresses -join \", \"\n    Write-Host \"$($i + 1). $processName ($ipAddresses)\"\n}\n\n# Log the process list to the file\n\"Process List:\" | Log-Output\nfor ($i = 0; $i -lt $processGroups.Count; $i++) {\n    $processName = $processGroups&#91;$i].ProcessName\n    $ipAddresses = $processGroups&#91;$i].IPAddresses -join \", \"\n    \"$($i + 1). $processName ($ipAddresses)\" | Log-Output\n}\n\n# Prompt the user to enter the number of the process they want to analyze\n$selectedProcessIndex = Read-Host \"Enter the number of the process\"\n\n# Validate the user's input\nwhile (&#91;int]$selectedProcessIndex -lt 1 -or &#91;int]$selectedProcessIndex -gt $processGroups.Count) {\n    Write-Host \"Invalid selection. Please enter a valid number.\"\n    $selectedProcessIndex = Read-Host \"Enter the number of the process\"\n}\n\n# Get the selected process name and IP addresses\n$selectedProcessName = $processGroups&#91;$selectedProcessIndex - 1].ProcessName\n$selectedProcessIpAddresses = $processGroups&#91;$selectedProcessIndex - 1].IPAddresses\n\n# Confirm the user's selection\nWrite-Host \"You selected: $selectedProcessName\"\n$confirmation = Read-Host \"Do you want to proceed with this process? (Y\/N) &#91;Y]\"\n\n# Validate the user's confirmation\nwhile ($confirmation -ne \"\" -and $confirmation -ne \"Y\" -and $confirmation -ne \"N\") {\n    Write-Host \"Invalid input. Please enter 'Y' or 'N' (default is 'Y').\"\n    $confirmation = Read-Host \"Do you want to proceed with this process? (Y\/N) &#91;Y]\"\n}\n\nif ($confirmation -eq \"N\") {\n    Write-Host \"Process selection canceled. Exiting script.\"\n    exit\n}\n\n# Display the IP addresses associated with the selected process\nWrite-Host \"\"\nWrite-Host \"The IP Addresses associated with the process $selectedProcessName are:\"\nforeach ($ipAddress in $selectedProcessIpAddresses) {\n    Write-Host $ipAddress\n}\nWrite-Host \"\"\n\n# Log the selected process and its IP addresses to the file\n\"Selected Process: $selectedProcessName\" | Log-Output\n\"IP Addresses:\" | Log-Output\nforeach ($ipAddress in $selectedProcessIpAddresses) {\n    $ipAddress | Log-Output\n}\n\n# Function to perform fast traceroute and return the output\nfunction Get-FastTraceroute {\n    param (\n        &#91;Parameter(Mandatory=$true)]\n        &#91;string]$traceDestination,\n        &#91;int]$waitTime = 100,\n        &#91;int]$maxTTL = 30\n    )\n\n    $resultTable = @()\n\n    for ($ttl = 1; $ttl -le $maxTTL; $ttl++) {\n        $pingOutput = &amp; ping -n 1 -i $ttl -w $waitTime $traceDestination\n\n        $expiredLine = $pingOutput | Select-String -Pattern \"TTL expired\"\n        if ($expiredLine -ne $null) {\n            $expiredIP = $expiredLine.ToString().Split(\" \")&#91;2].TrimEnd(\":\")\n            $resultTable += &#91;PSCustomObject]@{\n                TTL = $ttl\n                ExpiredIP = $expiredIP\n            }\n        }\n    }\n\n    $reachable = Test-Connection -ComputerName $traceDestination -Count 1 -Quiet\n\n    return &#91;PSCustomObject]@{\n        TraceDestination = $traceDestination\n        PingResults = $resultTable\n        Reachable = $reachable\n    }\n}\n\n# Create an empty array to store the traceroute results\n$tracerouteResults = @()\n\n# Perform traceroute for each IP address related to the selected process\nforeach ($ipAddress in $selectedProcessIpAddresses) {\n    Write-Host \"Starting traceroute for IP address: $ipAddress\"\n    $traceroute = Get-FastTraceroute -traceDestination $ipAddress\n    $tracerouteResults += &#91;PSCustomObject]@{\n        IPAddress = $ipAddress\n        Traceroute = $traceroute.PingResults\n    }\n\n    # Log the traceroute results to the file\n    \"Traceroute for IP Address: $ipAddress\" | Log-Output\n    foreach ($hop in $traceroute.PingResults) {\n        \"TTL: $($hop.TTL), Expired IP: $($hop.ExpiredIP)\" | Log-Output\n    }\n}\n\n# Sort the traceroute results based on the number of hops (smallest to largest)\n$tracerouteResults = $tracerouteResults | Sort-Object -Property { $_.Traceroute.Count }\n\n# Create the tree structure\n$tree = @{}\nforeach ($result in $tracerouteResults) {\n    $ipAddress = $result.IPAddress\n    $traceroute = $result.Traceroute\n\n    $currentNode = $tree\n    foreach ($hop in $traceroute) {\n        $hopIP = $hop.ExpiredIP\n        if ($currentNode.ContainsKey($hopIP)) {\n            $currentNode = $currentNode&#91;$hopIP]\n        }\n        else {\n            $currentNode&#91;$hopIP] = @{}\n            $currentNode = $currentNode&#91;$hopIP]\n        }\n    }\n    $currentNode&#91;$ipAddress] = $null\n}\n\n# Generate the tree output\nfunction Generate-TreeOutput($node, $depth, $prefix) {\n    $output = \"\"\n    $lastIndex = $node.Keys.Count - 1\n    foreach ($key in $node.Keys) {\n        $isLast = $node.Keys.IndexOf($key) -eq $lastIndex\n        $line = $prefix + $(if ($isLast) { \"\u2514\u2500\" } else { \"\u251c\u2500\" }) + $key\n        $output += $line + \"`n\"\n        if ($node&#91;$key] -ne $null) {\n            $childPrefix = $prefix + $(if ($isLast) { \"  \" } else { \"\u2502 \" })\n            $output += Generate-TreeOutput $node&#91;$key] ($depth + 1) $childPrefix\n        }\n    }\n    return $output\n}\n\n$treeOutput = Generate-TreeOutput $tree 0 \"\"\n\n# Display the tree output\nWrite-Host \"Traceroute Tree:\"\nWrite-Host $treeOutput\n\n# Log the traceroute tree to the file\n\"Traceroute Tree:\" | Log-Output\n$treeOutput | Log-Output\n\n# Get the 1st, 2nd, and last responding IP addresses from the traceroute results\n$pingIpAddresses = @()\n$pingIpAddresses += $tracerouteResults&#91;0].Traceroute | Select-Object -First 1 | Select-Object -ExpandProperty ExpiredIP\n$pingIpAddresses += $tracerouteResults&#91;0].Traceroute | Select-Object -Skip 1 | Select-Object -First 1 | Select-Object -ExpandProperty ExpiredIP\n$pingIpAddresses += $tracerouteResults | ForEach-Object { $_.Traceroute | Select-Object -Last 1 | Select-Object -ExpandProperty ExpiredIP } | Select-Object -Last 1\n\n# Check if there are any responding IP addresses\nif ($pingIpAddresses -contains $null) {\n    Write-Host \"No responding IP addresses found for the selected process. Exiting script.\"\n    exit\n}\n\n# Set the maximum response time for padding\n$maxResponseTime = 25\n\nfunction Ping-And-Display {\n    while ($true) {\n        $outputs = @()\n\n        foreach ($ipAddress in $pingIpAddresses) {\n            # Send a single ping to the IP address\n            $pingResult = Test-Connection -ComputerName $ipAddress -Count 1 -ErrorAction SilentlyContinue\n            \n            if ($pingResult) {\n                # Check if the response time is 0ms\n                if ($pingResult.ResponseTime -eq 0) {\n                    $line = \"0\"\n                }\n                elseif ($pingResult.ResponseTime -le $maxResponseTime) {\n                    # Generate a string of 'X's equal to the response time\n                    $line = 'X' * $pingResult.ResponseTime\n                }\n                else {\n                    # Display the response time if it exceeds the maximum\n                    $line = $pingResult.ResponseTime.ToString()\n                }\n                \n                # Pad the line to align the columns\n                $paddedLine = $line.PadRight($maxResponseTime)\n                \n                # Prepend the IP address\n                $output = \"$ipAddress $paddedLine\"\n            }\n            else {\n                # If ping fails, generate a line of dashes equal to the maximum response time\n                $output = \"$ipAddress \" + ('-' * $maxResponseTime)\n            }\n            \n            # Add the output to the array\n            $outputs += $output\n        }\n        \n        # Join the outputs with a separator\n        $combinedOutput = $outputs -join \" | \"\n        \n        # Output the combined line to the screen\n        Write-Output $combinedOutput\n        \n        # Log the combined output to the file\n        $combinedOutput | Log-Output\n        \n        # Wait for 1 second before the next ping\n        Start-Sleep -Seconds 1\n    }\n}\n\n# Start the ping and display process\nPing-And-Display<\/code><\/pre>\n\n\n\n<p>TreePing my balls off<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#TreePing has issues\n# Set the log file path\n$Logfile = \".\\ping.log\"\n\n# Define the logging function\nfunction Log-Output {\n    param (\n        &#91;Parameter(Mandatory=$true, ValueFromPipeline=$true)]\n        &#91;string]$Message\n    )\n\n    $timestamp = Get-Date -Format \"yyyy-MM-dd.HH:mm:ss\"\n    \"$timestamp $Message\" | Out-File -Append -FilePath $Logfile\n}\n\n# Get all active network connections\n$connections = Get-NetTCPConnection | Where-Object { $_.State -eq \"Established\" }\n\n# Create an empty array to store the results\n$results = @()\n\n# Iterate through each active connection\nforeach ($connection in $connections) {\n    # Get the process ID (PID) associated with the connection\n    $processId = $connection.OwningProcess\n\n    # Get the process information based on the PID\n    $process = Get-Process -Id $processId -ErrorAction SilentlyContinue\n\n    # Create a custom object to store the connection details\n    $result = &#91;PSCustomObject]@{\n        LocalAddress  = $connection.LocalAddress\n        LocalPort     = $connection.LocalPort\n        RemoteAddress = $connection.RemoteAddress\n        RemotePort    = $connection.RemotePort\n        State         = $connection.State\n        ProcessName   = $process.ProcessName\n        ProcessId     = $processId\n    }\n\n    # Add the custom object to the results array\n    $results += $result\n}\n\n# Group the results by process name and get the unique remote IP addresses for each process\n$processGroups = $results | Group-Object -Property ProcessName | ForEach-Object {\n    $processName = $_.Name\n    $processIpAddresses = $_.Group |\n        Select-Object -ExpandProperty RemoteAddress |\n        Where-Object { $_ -ne \"127.0.0.1\" -and $_ -ne \"::1\" } |\n        Select-Object -Unique\n\n    &#91;PSCustomObject]@{\n        ProcessName = $processName\n        IPAddresses = $processIpAddresses\n    }\n}\n\n# Display the numbered list of processes with their associated IP addresses\nWrite-Host \"Select a process to analyze:\"\nfor ($i = 0; $i -lt $processGroups.Count; $i++) {\n    $processName = $processGroups&#91;$i].ProcessName\n    $ipAddresses = $processGroups&#91;$i].IPAddresses -join \", \"\n    Write-Host \"$($i + 1). $processName ($ipAddresses)\"\n}\n\n# Log the process list to the file\n\"Process List:\" | Log-Output\nfor ($i = 0; $i -lt $processGroups.Count; $i++) {\n    $processName = $processGroups&#91;$i].ProcessName\n    $ipAddresses = $processGroups&#91;$i].IPAddresses -join \", \"\n    \"$($i + 1). $processName ($ipAddresses)\" | Log-Output\n}\n\n# Prompt the user to enter the number of the process they want to analyze\n$selectedProcessIndex = Read-Host \"Enter the number of the process\"\n\n# Validate the user's input\nwhile (&#91;int]$selectedProcessIndex -lt 1 -or &#91;int]$selectedProcessIndex -gt $processGroups.Count) {\n    Write-Host \"Invalid selection. Please enter a valid number.\"\n    $selectedProcessIndex = Read-Host \"Enter the number of the process\"\n}\n\n# Get the selected process name and IP addresses\n$selectedProcessName = $processGroups&#91;$selectedProcessIndex - 1].ProcessName\n$selectedProcessIpAddresses = $processGroups&#91;$selectedProcessIndex - 1].IPAddresses\n\n# Confirm the user's selection\nWrite-Host \"You selected: $selectedProcessName\"\n$confirmation = Read-Host \"Do you want to proceed with this process? (Y\/N) &#91;Y]\"\n\n# Validate the user's confirmation\nwhile ($confirmation -ne \"\" -and $confirmation -ne \"Y\" -and $confirmation -ne \"N\") {\n    Write-Host \"Invalid input. Please enter 'Y' or 'N' (default is 'Y').\"\n    $confirmation = Read-Host \"Do you want to proceed with this process? (Y\/N) &#91;Y]\"\n}\n\nif ($confirmation -eq \"N\") {\n    Write-Host \"Process selection canceled. Exiting script.\"\n    exit\n}\n\n# Display the IP addresses associated with the selected process\nWrite-Host \"\"\nWrite-Host \"The IP Addresses associated with the process $selectedProcessName are:\"\nforeach ($ipAddress in $selectedProcessIpAddresses) {\n    Write-Host $ipAddress\n}\nWrite-Host \"\"\n\n# Log the selected process and its IP addresses to the file\n\"Selected Process: $selectedProcessName\" | Log-Output\n\"IP Addresses:\" | Log-Output\nforeach ($ipAddress in $selectedProcessIpAddresses) {\n    $ipAddress | Log-Output\n}\n\n# Function to perform fast traceroute and return the output\nfunction Get-FastTraceroute {\n    param (\n        &#91;Parameter(Mandatory=$true)]\n        &#91;string]$traceDestination,\n        &#91;int]$waitTime = 100,\n        &#91;int]$maxTTL = 30\n    )\n\n    $resultTable = @()\n\n    for ($ttl = 1; $ttl -le $maxTTL; $ttl++) {\n        $pingOutput = &amp; ping -n 1 -i $ttl -w $waitTime $traceDestination\n\n        $expiredLine = $pingOutput | Select-String -Pattern \"TTL expired\"\n        if ($expiredLine -ne $null) {\n            $expiredIP = $expiredLine.ToString().Split(\" \")&#91;2].TrimEnd(\":\")\n            $resultTable += &#91;PSCustomObject]@{\n                TTL = $ttl\n                ExpiredIP = $expiredIP\n            }\n        }\n    }\n\n    $reachable = Test-Connection -ComputerName $traceDestination -Count 1 -Quiet\n\n    return &#91;PSCustomObject]@{\n        TraceDestination = $traceDestination\n        PingResults = $resultTable\n        Reachable = $reachable\n    }\n}\n\n# Create an empty array to store the traceroute results\n$tracerouteResults = @()\n\n# Perform traceroute for each IP address related to the selected process\nforeach ($ipAddress in $selectedProcessIpAddresses) {\n    Write-Host \"Starting traceroute for IP address: $ipAddress\"\n    $traceroute = Get-FastTraceroute -traceDestination $ipAddress\n    $tracerouteResults += &#91;PSCustomObject]@{\n        IPAddress = $ipAddress\n        Traceroute = $traceroute.PingResults\n    }\n\n    # Log the traceroute results to the file\n    \"Traceroute for IP Address: $ipAddress\" | Log-Output\n    foreach ($hop in $traceroute.PingResults) {\n        \"TTL: $($hop.TTL), Expired IP: $($hop.ExpiredIP)\" | Log-Output\n    }\n}\n\n# Sort the traceroute results based on the number of hops (smallest to largest)\n$tracerouteResults = $tracerouteResults | Sort-Object -Property { $_.Traceroute.Count }\n\n# Create the tree structure\n$tree = @{}\nforeach ($result in $tracerouteResults) {\n    $ipAddress = $result.IPAddress\n    $traceroute = $result.Traceroute\n\n    $currentNode = $tree\n    foreach ($hop in $traceroute) {\n        $hopIP = $hop.ExpiredIP\n        if ($currentNode.ContainsKey($hopIP)) {\n            $currentNode = $currentNode&#91;$hopIP]\n        }\n        else {\n            $currentNode&#91;$hopIP] = @{}\n            $currentNode = $currentNode&#91;$hopIP]\n        }\n    }\n    $currentNode&#91;$ipAddress] = $null\n}\n\n# Generate the tree output with ping responses\nfunction Generate-TreeOutput($node, $depth, $prefix) {\n    $output = \"\"\n    $lastIndex = $node.Keys.Count - 1\n    foreach ($key in $node.Keys) {\n        $isLast = $node.Keys.IndexOf($key) -eq $lastIndex\n        \n        # Send a single ping to the IP address\n        $pingResult = Test-Connection -ComputerName $key -Count 1 -ErrorAction SilentlyContinue\n        \n        if ($pingResult) {\n            # Check if the response time is 0ms\n            if ($pingResult.ResponseTime -eq 0) {\n                $pingResponse = \"0\"\n            }\n            elseif ($pingResult.ResponseTime -le 25) {\n                # Generate a string of 'X's equal to the response time\n                $pingResponse = 'X' * $pingResult.ResponseTime\n            }\n            else {\n                # Display the response time if it exceeds 25ms\n                $pingResponse = $pingResult.ResponseTime.ToString()\n            }\n        }\n        else {\n            # If ping fails, generate a string of dashes\n            $pingResponse = \"-\" * 10\n        }\n        \n        $line = $prefix + $(if ($isLast) { \"\u2514\u2500\" } else { \"\u251c\u2500\" }) + \"$key $pingResponse\"\n        $output += $line + \"`n\"\n        if ($node&#91;$key] -ne $null) {\n            $childPrefix = $prefix + $(if ($isLast) { \"  \" } else { \"\u2502 \" })\n            $output += Generate-TreeOutput $node&#91;$key] ($depth + 1) $childPrefix\n        }\n    }\n    return $output\n}\n\n# Function to continuously ping and display the traceroute tree\nfunction Ping-And-Display {\n    $previousTreeOutput = \"\"\n    \n    while ($true) {\n        # Generate the tree output with ping responses\n        $treeOutput = Generate-TreeOutput $tree 0 \"\"\n        \n        # Clear the screen only if the tree output has changed\n        if ($treeOutput -ne $previousTreeOutput) {\n            Clear-Host\n            \n            # Display the tree output\n            Write-Host \"Traceroute Tree:\" -NoNewline\n            Write-Host \"`r$treeOutput\" -NoNewline\n            \n            # Log the traceroute tree to the file\n            \"Traceroute Tree:\" | Log-Output\n            $treeOutput | Log-Output\n            \n            $previousTreeOutput = $treeOutput\n        }\n        \n        # Wait for 1 second before the next ping\n        Start-Sleep -Seconds 1\n    }\n}\n# Start the ping and display process\nPing-And-Display<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>I thought I would do some-ping awesome! TreePing my balls off<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-50","page","type-page","status-publish","hentry"],"jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.scothargan.com\/index.php?rest_route=\/wp\/v2\/pages\/50","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.scothargan.com\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.scothargan.com\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.scothargan.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.scothargan.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=50"}],"version-history":[{"count":1,"href":"https:\/\/www.scothargan.com\/index.php?rest_route=\/wp\/v2\/pages\/50\/revisions"}],"predecessor-version":[{"id":51,"href":"https:\/\/www.scothargan.com\/index.php?rest_route=\/wp\/v2\/pages\/50\/revisions\/51"}],"wp:attachment":[{"href":"https:\/\/www.scothargan.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=50"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}