Fixed memory usage, stop automatically after 24h
This commit is contained in:
255
Ping_Monitor.ps1
255
Ping_Monitor.ps1
@@ -4,7 +4,6 @@ $addressDefinitions = @(
|
|||||||
"1.1.1.1",
|
"1.1.1.1",
|
||||||
"1.0.0.1",
|
"1.0.0.1",
|
||||||
"8.8.8.8-9" # Using range notation for cleaner definition
|
"8.8.8.8-9" # Using range notation for cleaner definition
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Set up logging configuration
|
# Set up logging configuration
|
||||||
@@ -19,29 +18,51 @@ if (-not (Test-Path $logFolder)) {
|
|||||||
New-Item -Path $logFolder -ItemType Directory | Out-Null
|
New-Item -Path $logFolder -ItemType Directory | Out-Null
|
||||||
}
|
}
|
||||||
|
|
||||||
# Initialize log files with headers
|
# Initialize log files with headers - Use streamwriter for lower memory footprint
|
||||||
if (-not (Test-Path $csvLogFile)) {
|
$null = if (-not (Test-Path $csvLogFile)) {
|
||||||
"Timestamp,IPAddress,Status,ResponseTime,SuccessRate" | Out-File -FilePath $csvLogFile
|
$csvStream = [System.IO.StreamWriter]::new($csvLogFile)
|
||||||
|
$csvStream.WriteLine("Timestamp,IPAddress,Status,ResponseTime,SuccessRate")
|
||||||
|
$csvStream.Close()
|
||||||
|
$csvStream.Dispose()
|
||||||
}
|
}
|
||||||
|
|
||||||
# Function to write to log file with timestamp
|
# Prepare log streamwriters - more memory efficient than Out-File
|
||||||
|
$logStream = $null
|
||||||
|
$statLogStream = $null
|
||||||
|
$errorLogStream = $null
|
||||||
|
$csvLogStream = $null
|
||||||
|
|
||||||
|
# Function to write to log file with timestamp - using streamwriter for efficiency
|
||||||
function Write-Log {
|
function Write-Log {
|
||||||
param(
|
param(
|
||||||
[Parameter(Mandatory=$true)]
|
[Parameter(Mandatory=$true)]
|
||||||
[string]$Message,
|
[string]$Message,
|
||||||
[string]$LogFile = $logFile,
|
[string]$LogPath = $logFile,
|
||||||
[switch]$NoConsole
|
[switch]$NoConsole
|
||||||
)
|
)
|
||||||
|
|
||||||
$timestamp = Get-Date -Format 'yyyy-MM-dd HH:mm:ss'
|
$timestamp = Get-Date -Format 'yyyy-MM-dd HH:mm:ss'
|
||||||
"$timestamp - $Message" | Out-File -FilePath $LogFile -Append
|
$logLine = "$timestamp - $Message"
|
||||||
|
|
||||||
|
# Use streamwriter instead of Out-File
|
||||||
|
$stream = [System.IO.StreamWriter]::new($LogPath, $true)
|
||||||
|
$stream.WriteLine($logLine)
|
||||||
|
$stream.Close()
|
||||||
|
$stream.Dispose()
|
||||||
|
|
||||||
if (-not $NoConsole) {
|
if (-not $NoConsole) {
|
||||||
Write-Host "$timestamp - $Message"
|
Write-Host $logLine
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Log script start
|
# Log script start
|
||||||
Write-Log "Network monitoring script started"
|
Write-Log "Network monitoring script started"
|
||||||
|
|
||||||
|
# Set script end time (24 hours from now)
|
||||||
|
$endTime = (Get-Date).AddHours(24)
|
||||||
|
Write-Log "Script will automatically stop at $($endTime.ToString('yyyy-MM-dd HH:mm:ss'))"
|
||||||
|
|
||||||
|
# Process IP address definitions more efficiently
|
||||||
foreach ($addr in $addressDefinitions) {
|
foreach ($addr in $addressDefinitions) {
|
||||||
if ($addr -match "(\d+\.\d+\.\d+\.)(\d+)-(\d+)") {
|
if ($addr -match "(\d+\.\d+\.\d+\.)(\d+)-(\d+)") {
|
||||||
$prefix = $matches[1]
|
$prefix = $matches[1]
|
||||||
@@ -58,28 +79,43 @@ foreach ($addr in $addressDefinitions) {
|
|||||||
# Log monitored addresses
|
# Log monitored addresses
|
||||||
Write-Log "Monitoring IP addresses: $($addresses -join ', ')"
|
Write-Log "Monitoring IP addresses: $($addresses -join ', ')"
|
||||||
|
|
||||||
# Initialize hashtables to store statistics
|
# Initialize statistics storage - Use simpler data structures for memory efficiency
|
||||||
|
$sampleSize = 60 # Maximum number of samples to keep
|
||||||
$stats = @{}
|
$stats = @{}
|
||||||
|
|
||||||
foreach ($addr in $addresses) {
|
foreach ($addr in $addresses) {
|
||||||
|
# Use fixed-size arrays instead of queue for better memory efficiency
|
||||||
$stats[$addr] = @{
|
$stats[$addr] = @{
|
||||||
MinTime = [int]::MaxValue
|
MinTime = [int]::MaxValue
|
||||||
MaxTime = 0
|
MaxTime = 0
|
||||||
TotalTime = 0
|
SampleArray = New-Object 'int[]' $sampleSize # Fixed-size array
|
||||||
|
SamplePosition = 0 # Current position in array
|
||||||
|
SampleCount = 0 # Current number of samples (up to sampleSize)
|
||||||
SuccessCount = 0
|
SuccessCount = 0
|
||||||
FailCount = 0
|
FailCount = 0
|
||||||
Samples = [System.Collections.Queue]::new(60) # Fixed-size queue for better memory management
|
|
||||||
LastStatus = $null
|
LastStatus = $null
|
||||||
StatusChanged = $false
|
|
||||||
LastLoggedStats = [DateTime]::MinValue
|
LastLoggedStats = [DateTime]::MinValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Function to calculate mean
|
# More efficient mean calculation for fixed array
|
||||||
function Get-Mean {
|
function Get-ArrayMean {
|
||||||
param($Numbers)
|
param(
|
||||||
if ($Numbers.Count -eq 0) { return 0 }
|
[int[]]$Array,
|
||||||
$array = [array]($Numbers)
|
[int]$Count,
|
||||||
return ($array | Measure-Object -Average).Average
|
[int]$Max
|
||||||
|
)
|
||||||
|
|
||||||
|
if ($Count -eq 0) { return 0 }
|
||||||
|
|
||||||
|
$sum = 0
|
||||||
|
$actualCount = [Math]::Min($Count, $Max)
|
||||||
|
|
||||||
|
for ($i = 0; $i -lt $actualCount; $i++) {
|
||||||
|
$sum += $Array[$i]
|
||||||
|
}
|
||||||
|
|
||||||
|
return $sum / $actualCount
|
||||||
}
|
}
|
||||||
|
|
||||||
# Function to clear the console and position cursor
|
# Function to clear the console and position cursor
|
||||||
@@ -88,7 +124,7 @@ function Reset-Display {
|
|||||||
$host.UI.RawUI.CursorPosition = @{X=0; Y=0}
|
$host.UI.RawUI.CursorPosition = @{X=0; Y=0}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Function to format number with fixed width
|
# Function to format number with fixed width - optimized to reduce string operations
|
||||||
function Format-Number {
|
function Format-Number {
|
||||||
param(
|
param(
|
||||||
[Parameter(Mandatory=$true)]
|
[Parameter(Mandatory=$true)]
|
||||||
@@ -96,26 +132,55 @@ function Format-Number {
|
|||||||
[int]$Width = 6,
|
[int]$Width = 6,
|
||||||
[int]$Decimals = 1
|
[int]$Decimals = 1
|
||||||
)
|
)
|
||||||
if ($Number -eq [int]::MaxValue) { return "".PadLeft($Width) }
|
|
||||||
return $Number.ToString("F$Decimals").PadLeft($Width)
|
if ($Number -eq [int]::MaxValue) {
|
||||||
|
return ' ' * $Width
|
||||||
}
|
}
|
||||||
|
|
||||||
# Function to log status changes
|
$formatted = [string]::Format("{0:F$Decimals}", $Number)
|
||||||
|
$padding = $Width - $formatted.Length
|
||||||
|
|
||||||
|
if ($padding -gt 0) {
|
||||||
|
return (' ' * $padding) + $formatted
|
||||||
|
}
|
||||||
|
return $formatted
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to log status changes - streamwriter based
|
||||||
function Write-StatusLog {
|
function Write-StatusLog {
|
||||||
param(
|
param(
|
||||||
[string]$Address,
|
[string]$Address,
|
||||||
[string]$OldStatus,
|
[bool]$OldStatus,
|
||||||
[string]$NewStatus
|
[bool]$NewStatus
|
||||||
)
|
)
|
||||||
$statusText = if ($NewStatus -eq $true) { "UP" } else { "DOWN" }
|
|
||||||
$oldStatusText = if ($OldStatus -eq $true) { "UP" } else { "DOWN" }
|
$statusText = if ($NewStatus) { "UP" } else { "DOWN" }
|
||||||
|
$oldStatusText = if ($OldStatus) { "UP" } else { "DOWN" }
|
||||||
$logMessage = "$Address status changed from $oldStatusText to $statusText"
|
$logMessage = "$Address status changed from $oldStatusText to $statusText"
|
||||||
|
|
||||||
Write-Log $logMessage
|
Write-Log $logMessage
|
||||||
Write-Host "`n$logMessage" -ForegroundColor Yellow
|
Write-Host "`n$logMessage" -ForegroundColor Yellow
|
||||||
}
|
}
|
||||||
|
|
||||||
# Function to log statistics periodically
|
# Function to log ping data to CSV - using streamwriter for efficiency
|
||||||
|
function Write-PingDataLog {
|
||||||
|
param(
|
||||||
|
[string]$Address,
|
||||||
|
[bool]$Status,
|
||||||
|
[int]$ResponseTime,
|
||||||
|
[double]$SuccessRate
|
||||||
|
)
|
||||||
|
|
||||||
|
$statusText = if ($Status) { "UP" } else { "DOWN" }
|
||||||
|
$timestamp = Get-Date -Format 'yyyy-MM-dd HH:mm:ss'
|
||||||
|
|
||||||
|
$stream = [System.IO.StreamWriter]::new($csvLogFile, $true)
|
||||||
|
$stream.WriteLine("$timestamp,$Address,$statusText,$ResponseTime,$SuccessRate")
|
||||||
|
$stream.Close()
|
||||||
|
$stream.Dispose()
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to log statistics periodically - streamwriter based
|
||||||
function Write-StatisticsLog {
|
function Write-StatisticsLog {
|
||||||
param(
|
param(
|
||||||
[string]$Address,
|
[string]$Address,
|
||||||
@@ -130,34 +195,18 @@ function Write-StatisticsLog {
|
|||||||
[math]::Round(($Statistics.SuccessCount / $totalRequests) * 100, 1)
|
[math]::Round(($Statistics.SuccessCount / $totalRequests) * 100, 1)
|
||||||
} else { 0 }
|
} else { 0 }
|
||||||
|
|
||||||
$meanTime = if ($Statistics.Samples.Count -gt 0) {
|
$meanTime = [math]::Round((Get-ArrayMean -Array $Statistics.SampleArray -Count $Statistics.SampleCount -Max $sampleSize), 1)
|
||||||
[math]::Round((Get-Mean $Statistics.Samples), 1)
|
|
||||||
} else { 0 }
|
|
||||||
|
|
||||||
$statsMessage = "$Address Stats - Min: $($Statistics.MinTime)ms, Max: $($Statistics.MaxTime)ms, " +
|
$statsMessage = "$Address Stats - Min: $($Statistics.MinTime)ms, Max: $($Statistics.MaxTime)ms, " +
|
||||||
"Mean: ${meanTime}ms, Success Rate: ${successRate}%, " +
|
"Mean: ${meanTime}ms, Success Rate: ${successRate}%, " +
|
||||||
"Success Count: $($Statistics.SuccessCount), Fail Count: $($Statistics.FailCount)"
|
"Success Count: $($Statistics.SuccessCount), Fail Count: $($Statistics.FailCount)"
|
||||||
|
|
||||||
Write-Log -Message $statsMessage -LogFile $statLogFile -NoConsole
|
Write-Log -Message $statsMessage -LogPath $statLogFile -NoConsole
|
||||||
$Statistics.LastLoggedStats = $now
|
$Statistics.LastLoggedStats = $now
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Function to log ping data to CSV
|
# Function to handle errors - streamwriter based
|
||||||
function Write-PingDataLog {
|
|
||||||
param(
|
|
||||||
[string]$Address,
|
|
||||||
[bool]$Status,
|
|
||||||
[int]$ResponseTime,
|
|
||||||
[double]$SuccessRate
|
|
||||||
)
|
|
||||||
|
|
||||||
$statusText = if ($Status) { "UP" } else { "DOWN" }
|
|
||||||
$timestamp = Get-Date -Format 'yyyy-MM-dd HH:mm:ss'
|
|
||||||
"$timestamp,$Address,$statusText,$ResponseTime,$SuccessRate" | Out-File -FilePath $csvLogFile -Append
|
|
||||||
}
|
|
||||||
|
|
||||||
# Function to handle errors
|
|
||||||
function Write-ErrorLog {
|
function Write-ErrorLog {
|
||||||
param(
|
param(
|
||||||
[Parameter(Mandatory=$true)]
|
[Parameter(Mandatory=$true)]
|
||||||
@@ -166,26 +215,55 @@ function Write-ErrorLog {
|
|||||||
)
|
)
|
||||||
|
|
||||||
$errorMessage = "[$Context] $($ErrorRecord.Exception.GetType().Name): $($ErrorRecord.Exception.Message)"
|
$errorMessage = "[$Context] $($ErrorRecord.Exception.GetType().Name): $($ErrorRecord.Exception.Message)"
|
||||||
$errorDetails = $ErrorRecord | Format-List * -Force | Out-String
|
|
||||||
|
|
||||||
Write-Log -Message $errorMessage -LogFile $errorLogFile -NoConsole
|
# More memory efficient than Format-List
|
||||||
Write-Log -Message "Details: $errorDetails" -LogFile $errorLogFile -NoConsole
|
$errorDetails = "Exception: $($ErrorRecord.Exception)"
|
||||||
|
|
||||||
|
Write-Log -Message $errorMessage -LogPath $errorLogFile -NoConsole
|
||||||
|
Write-Log -Message "Details: $errorDetails" -LogPath $errorLogFile -NoConsole
|
||||||
Write-Host "Error: $errorMessage" -ForegroundColor Red
|
Write-Host "Error: $errorMessage" -ForegroundColor Red
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Function to display time remaining
|
||||||
|
function Format-TimeRemaining {
|
||||||
|
param([TimeSpan]$TimeSpan)
|
||||||
|
return "{0:D2}:{1:D2}:{2:D2}" -f $TimeSpan.Hours, $TimeSpan.Minutes, $TimeSpan.Seconds
|
||||||
|
}
|
||||||
|
|
||||||
|
# Memory cleanup function - call periodically
|
||||||
|
function Invoke-MemoryCleanup {
|
||||||
|
[System.GC]::Collect()
|
||||||
|
[System.GC]::WaitForPendingFinalizers()
|
||||||
|
[System.GC]::Collect()
|
||||||
|
}
|
||||||
|
|
||||||
# Main monitoring loop
|
# Main monitoring loop
|
||||||
try {
|
try {
|
||||||
$pingInterval = 1 # seconds between pings
|
$pingInterval = 1 # seconds between pings
|
||||||
$statsLogInterval = 15 # minutes between logging statistics
|
$statsLogInterval = 15 # minutes between logging statistics
|
||||||
$csvLogFrequency = 5 # log every Nth ping to CSV to avoid huge files
|
$csvLogFrequency = 5 # log every Nth ping to CSV to avoid huge files
|
||||||
|
$memoryCleanupInterval = 100 # Garbage collect every N pings
|
||||||
$pingCounter = 0
|
$pingCounter = 0
|
||||||
|
|
||||||
|
# Create ping object once, outside the loop
|
||||||
|
$ping = New-Object System.Net.NetworkInformation.Ping
|
||||||
|
|
||||||
Write-Log "Monitoring started with ping interval of ${pingInterval}s and stats logging every ${statsLogInterval} minutes"
|
Write-Log "Monitoring started with ping interval of ${pingInterval}s and stats logging every ${statsLogInterval} minutes"
|
||||||
|
|
||||||
while ($true) {
|
while ($true) {
|
||||||
|
# Check if 24 hours have elapsed
|
||||||
|
$currentTime = Get-Date
|
||||||
|
if ($currentTime -ge $endTime) {
|
||||||
|
Write-Log "24-hour monitoring period completed. Stopping the script."
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
$timeRemaining = $endTime - $currentTime
|
||||||
|
|
||||||
Reset-Display
|
Reset-Display
|
||||||
$currentTime = Get-Date -Format "HH:mm:ss"
|
$currentTimeFormatted = $currentTime.ToString("HH:mm:ss")
|
||||||
Write-Host "Network Monitor - Last Updated: $currentTime" -ForegroundColor Cyan
|
Write-Host "Network Monitor - Last Updated: $currentTimeFormatted" -ForegroundColor Cyan
|
||||||
|
Write-Host "Time remaining: $(Format-TimeRemaining -TimeSpan $timeRemaining)" -ForegroundColor Cyan
|
||||||
Write-Host "Press Ctrl+C to exit`n" -ForegroundColor DarkGray
|
Write-Host "Press Ctrl+C to exit`n" -ForegroundColor DarkGray
|
||||||
|
|
||||||
# Header with fixed widths
|
# Header with fixed widths
|
||||||
@@ -194,8 +272,12 @@ try {
|
|||||||
|
|
||||||
$pingCounter++
|
$pingCounter++
|
||||||
|
|
||||||
|
# Force garbage collection periodically
|
||||||
|
if ($pingCounter % $memoryCleanupInterval -eq 0) {
|
||||||
|
Invoke-MemoryCleanup
|
||||||
|
}
|
||||||
|
|
||||||
foreach ($addr in $addresses) {
|
foreach ($addr in $addresses) {
|
||||||
$ping = New-Object System.Net.NetworkInformation.Ping
|
|
||||||
try {
|
try {
|
||||||
$result = $ping.Send($addr, 1000) # 1 second timeout
|
$result = $ping.Send($addr, 1000) # 1 second timeout
|
||||||
$status = $result.Status -eq 'Success'
|
$status = $result.Status -eq 'Success'
|
||||||
@@ -207,18 +289,23 @@ try {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($status) {
|
if ($status) {
|
||||||
$stats[$addr].TotalTime += $responseTime
|
|
||||||
$stats[$addr].SuccessCount++
|
$stats[$addr].SuccessCount++
|
||||||
|
|
||||||
# Update rolling queue of samples - suppress output
|
# Update sample array using fixed position tracking
|
||||||
if ($stats[$addr].Samples.Count -eq 60) {
|
$position = $stats[$addr].SamplePosition
|
||||||
[void]$stats[$addr].Samples.Dequeue()
|
$stats[$addr].SampleArray[$position] = $responseTime
|
||||||
|
$stats[$addr].SamplePosition = ($position + 1) % $sampleSize
|
||||||
|
if ($stats[$addr].SampleCount -lt $sampleSize) {
|
||||||
|
$stats[$addr].SampleCount++
|
||||||
}
|
}
|
||||||
[void]$stats[$addr].Samples.Enqueue($responseTime)
|
|
||||||
|
|
||||||
# Update min/max
|
# Update min/max
|
||||||
$stats[$addr].MinTime = [Math]::Min($stats[$addr].MinTime, $responseTime)
|
if ($stats[$addr].MinTime -eq [int]::MaxValue -or $responseTime -lt $stats[$addr].MinTime) {
|
||||||
$stats[$addr].MaxTime = [Math]::Max($stats[$addr].MaxTime, $responseTime)
|
$stats[$addr].MinTime = $responseTime
|
||||||
|
}
|
||||||
|
if ($responseTime -gt $stats[$addr].MaxTime) {
|
||||||
|
$stats[$addr].MaxTime = $responseTime
|
||||||
|
}
|
||||||
|
|
||||||
$statusText = "UP"
|
$statusText = "UP"
|
||||||
$color = "Green"
|
$color = "Green"
|
||||||
@@ -233,9 +320,8 @@ try {
|
|||||||
$successRate = if ($totalRequests -gt 0) {
|
$successRate = if ($totalRequests -gt 0) {
|
||||||
[math]::Round(($stats[$addr].SuccessCount / $totalRequests) * 100, 1)
|
[math]::Round(($stats[$addr].SuccessCount / $totalRequests) * 100, 1)
|
||||||
} else { 0 }
|
} else { 0 }
|
||||||
$meanTime = if ($stats[$addr].Samples.Count -gt 0) {
|
|
||||||
[math]::Round((Get-Mean $stats[$addr].Samples), 1)
|
$meanTime = [math]::Round((Get-ArrayMean -Array $stats[$addr].SampleArray -Count $stats[$addr].SampleCount -Max $sampleSize), 1)
|
||||||
} else { 0 }
|
|
||||||
|
|
||||||
# Check for status changes and log them
|
# Check for status changes and log them
|
||||||
if ($null -ne $stats[$addr].LastStatus -and $stats[$addr].LastStatus -ne $status) {
|
if ($null -ne $stats[$addr].LastStatus -and $stats[$addr].LastStatus -ne $status) {
|
||||||
@@ -251,19 +337,32 @@ try {
|
|||||||
Write-PingDataLog -Address $addr -Status $status -ResponseTime $responseTime -SuccessRate $successRate
|
Write-PingDataLog -Address $addr -Status $status -ResponseTime $responseTime -SuccessRate $successRate
|
||||||
}
|
}
|
||||||
|
|
||||||
# Calculate trend based on last 5 samples - suppress output
|
# Calculate trend more efficiently
|
||||||
$trend = if ($stats[$addr].Samples.Count -ge 5) {
|
$trend = "━" # Default to neutral
|
||||||
$recent = @([array]($stats[$addr].Samples))
|
if ($stats[$addr].SampleCount -ge 5) {
|
||||||
$lastFive = $recent[-[Math]::Min(5, $recent.Count)..-1]
|
$samples = $stats[$addr].SampleArray
|
||||||
if ($lastFive.Count -ge 2) {
|
$count = $stats[$addr].SampleCount
|
||||||
$slope = ($lastFive[-1] - $lastFive[0]) / [Math]::Max(1, ($lastFive.Count - 1))
|
$position = $stats[$addr].SamplePosition
|
||||||
if ([Math]::Abs($slope) -lt 1) { "━" }
|
|
||||||
elseif ($slope -lt 0) { "↓" }
|
|
||||||
else { "↑" }
|
|
||||||
} else { "━" }
|
|
||||||
} else { "━" }
|
|
||||||
|
|
||||||
# Format output fields
|
# Get first sample (oldest of last 5)
|
||||||
|
$firstIndex = ($position - 5 + $sampleSize) % $sampleSize
|
||||||
|
$first = $samples[$firstIndex]
|
||||||
|
|
||||||
|
# Get last sample (newest)
|
||||||
|
$lastIndex = ($position - 1 + $sampleSize) % $sampleSize
|
||||||
|
$last = $samples[$lastIndex]
|
||||||
|
|
||||||
|
$slope = $last - $first
|
||||||
|
if ([Math]::Abs($slope) -lt 5) {
|
||||||
|
$trend = "━"
|
||||||
|
} elseif ($slope -lt 0) {
|
||||||
|
$trend = "↓"
|
||||||
|
} else {
|
||||||
|
$trend = "↑"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Format output fields - efficient string formatting
|
||||||
$ipField = $addr.PadRight(15)
|
$ipField = $addr.PadRight(15)
|
||||||
$statusField = $statusText.PadRight(8)
|
$statusField = $statusText.PadRight(8)
|
||||||
$minField = Format-Number -Number $stats[$addr].MinTime -Width 5 -Decimals 0
|
$minField = Format-Number -Number $stats[$addr].MinTime -Width 5 -Decimals 0
|
||||||
@@ -284,8 +383,16 @@ try {
|
|||||||
# Log any unhandled exceptions
|
# Log any unhandled exceptions
|
||||||
Write-ErrorLog -ErrorRecord $_ -Context "Main monitoring loop"
|
Write-ErrorLog -ErrorRecord $_ -Context "Main monitoring loop"
|
||||||
} finally {
|
} finally {
|
||||||
|
# Final garbage collection and cleanup
|
||||||
|
Invoke-MemoryCleanup
|
||||||
|
|
||||||
# Cleanup when script is interrupted
|
# Cleanup when script is interrupted
|
||||||
$endMessage = "Monitoring stopped at $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')"
|
$endMessage = "Monitoring stopped at $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')"
|
||||||
Write-Log $endMessage
|
Write-Log $endMessage
|
||||||
Write-Host "`n$endMessage" -ForegroundColor Cyan
|
Write-Host "`n$endMessage" -ForegroundColor Cyan
|
||||||
|
|
||||||
|
# Dispose of ping object
|
||||||
|
if ($ping -ne $null) {
|
||||||
|
$ping.Dispose()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user