Monitor de puertos

monitor de puertos.ps1

Este script en PowerShell crea una aplicación gráfica que permite a los administradores de sistemas monitorear conexiones TCP/IP a un host y puerto específicos, registrando los resultados en un archivo de log. Además, proporciona una interfaz de usuario intuitiva para visualizar y filtrar resultados.

Funciones principales

Voy a describir las funciones principales que componene este script

Función CheckConnection:


function CheckConeccion {
    param($targetHost, $port, $logFile)
    while ($true) {
        $startTime = [DateTime]::Now
        try {
            $tcpClient = New-Object System.Net.Sockets.TcpClient
            $tcpClient.ReceiveTimeout = 320
            $tcpClient.SendTimeout = 320
            $tcpClient.Connect($targetHost, $port)
            if ($tcpClient.Connected) {
                $endTime = [DateTime]::Now
                $responseTime = ($endTime - $startTime).TotalMilliseconds
                $logMessage = "[$(Get-Date -Format "HH:mm:ss")] Conexión exitosa al puerto $port en $targetHost - Tiempo de respuesta: $responseTime ms"
                Add-Content -Path $logFile -Value $logMessage
                $tcpClient.Close()
            }
        } catch [System.Net.Sockets.SocketException] {
            $logMessage = "[$(Get-Date -Format "HH:mm:ss")] No se pudo establecer la conexión al puerto $port en $targetHost (error de socket)"
            Add-Content -Path $logFile -Value $logMessage
        } catch {
            $logMessage = "[$(Get-Date -Format "HH:mm:ss")] No se pudo establecer la conexión al puerto $port en $targetHost (error desconocido)"
            Add-Content -Path $logFile -Value $logMessage
        } finally {
            if ($null -ne $tcpClient) {
                $tcpClient.Close()
                $tcpClient = $null
            }
        }
        Start-Sleep -Seconds 2
        if ($script:stopFlag) { break }
    }
}

¡Copiado!
Descripcion: Esta función se encarga de realizar una conexión TCP a un servidor y puerto específicos. Si la conexión es exitosa, calcula el tiempo de respuesta y registra la conexión exitosa en un archivo de log. Si no se puede conectar, también lo registra en el log.
  • Intenta establecer una conexión TCP con el host/puerto especificados.
  • Si tiene éxito, registra un mensaje con el tiempo de respuesta.
  • Si falla, registra un error (distinguiendo entre un error de socket o desconocido).
  • El bucle se detiene si se establece una bandera global ($script:stopFlag).
  • Propósito: Monitorear la conectividad a un puerto TCP en tiempo real y registrar los resultados.

    $timer.Add_Tick:

    
    $timer.Add_Tick({
        if ($null -ne $Global:script:logJob) {
            $output = Receive-Job $Global:script:logJob
            if ($output) {
                $SalidaResultados.SuspendLayout()
                $SalidaResultados.SelectionStart = $SalidaResultados.TextLength
                $SalidaResultados.SelectionLength = 0
                
                foreach ($line in $output.Split("`n")) {
                    $line = $line.Trim()
                    if ($line -match "No se pudo establecer la conexión") {
                        $SalidaResultados.SelectionColor = [System.Drawing.Color]::Red
                    } elseif ($line -match "Conexión exitosa") {
                        $SalidaResultados.SelectionColor = [System.Drawing.Color]::Green
                    } else {
                        $SalidaResultados.SelectionColor = $SalidaResultados.ForeColor
                    }
                    $SalidaResultados.AppendText($line + "`r`n")
                }
                
                $SalidaResultados.ScrollToCaret()
                $SalidaResultados.ResumeLayout()
            }
        }
    })
    
    
    ¡Copiado!
  • Descripcion: Esta función está asociada al evento de clic de un botón llamado $BMostrarTodo.
    • Verifica si el job de log está activo:
      • Comprueba si $Global:script:logJob no es nulo.
    • Recibe la salida del job de log:
      • Usa Receive-Job para obtener la salida del job de log.
    • Si hay salida disponible:
      • Suspende el diseño del control $SalidaResultados para mejorar el rendimiento mientras se actualiza el contenido.
      • Establece el punto de inicio de la selección en la longitud actual del texto del control.
      • Establece la longitud de la selección en 0 para asegurarse de que no haya texto seleccionado previamente.
    • Procesa cada línea de la salida:
      • Divide la salida en líneas usando Split("n")`.
      • Para cada línea, elimina los espacios en blanco al principio y al final con Trim().
      • Dependiendo del contenido de la línea, establece el color de selección:
        • Si la línea contiene "No se pudo establecer la conexión", el color de selección se establece en rojo ([System.Drawing.Color]::Red).
        • Si la línea contiene "Conexión exitosa", el color de selección se establece en verde ([System.Drawing.Color]::Green).
        • Si no coincide con ninguna de las condiciones anteriores, el color de selección se establece en el color de texto predeterminado del control ($SalidaResultados.ForeColor).
      • Añade la línea al control de salida usando AppendText() y añade un retorno de carro y nueva línea (\r\n).
    • Desplaza el cursor al final del texto:
      • Llama a ScrollToCaret() para asegurarse de que el control de salida se desplace automáticamente hasta la última línea añadida.
    • Desplaza el control de salida hasta el final:
      • Llama a ScrollToCaret() para asegurarse de que el control de salida se desplace automáticamente hasta la última línea añadida.
    • Reanuda el diseño del control:
      • Llama a ResumeLayout() para reanudar el diseño del control después de haber añadido todas las líneas.
  • Proposito: Esta función actualiza el control de salida con las líneas recibidas del job de log, coloreando las líneas específicas según su contenido para resaltar errores de conexión en rojo y conexiones exitosas en verde.
  • Funcion ReadLogFile:

    
    #actualiza la interfaz gráfica con nuevas líneas del log.
    function ReadLogFile {
        param($logFile)
        $lastPosition = 0
        while ($true) {
            if (Test-Path $logFile) {
                $fileContent = Get-Content $logFile -Raw
                if ($fileContent.Length -gt $lastPosition) {
                    $newContent = $fileContent.Substring($lastPosition)
                    $lastPosition = $fileContent.Length
                    Write-Output $newContent
                }
            }
            Start-Sleep -Milliseconds 500
            if ($script:stopFlag) { break }
        }
    }
    
    
    ¡Copiado!
    Descripcion:Esta función lee un archivo de log y muestra las nuevas líneas que se agregan al archivo en tiempo real.
  • Mantiene un lastPosition para leer solo las líneas nuevas que se agregan.
  • Muestra cada línea nueva que se añade al archivo de log.
  • Proposito:Leer y mostrar en tiempo real las entradas de un archivo de log.

    Funcion $startButton.Add_Click():

    
    $startButton.Add_Click({
        # Validar entradas
        if ([string]::IsNullOrWhiteSpace($TBObjetivo.Text) -or [string]::IsNullOrWhiteSpace($TBPuerto.Text)) {
            [System.Windows.Forms.MessageBox]::Show("Debe ingresar una IP y un puerto válidos.", "Error", [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
            return
        }
        $script:stopFlag = $false
        $targetHost = $TBObjetivo.Text
        $port = [int]$TBPuerto.Text
        $logFile = $TBArchivo.Text
        if($targetHost -eq ""){}
        # Limpiar el archivo de log antes de comenzar
        Clear-Content -Path $logFile -ErrorAction SilentlyContinue
    
        $Global:script:job = Start-Job -ScriptBlock ${function:CheckConeccion} -ArgumentList $targetHost, $port, $logFile
        $Global:script:logJob = Start-Job -ScriptBlock ${function:ReadLogFile} -ArgumentList $logFile
        $startButton.Enabled = $false
        $BDetener.Enabled = $true
        
        # Limpiar la salida en la GUI
        $SalidaResultados.Clear()
        $script:allLines = @()
    })
    
    
    ¡Copiado!
    Descripcion:Esta diseñada para iniciar un proceso de verificación de conexión y registrar los resultados en un archivo de log, mientras actualiza la interfaz de usuario para reflejar el estado del proceso.
  • Validación de Entradas:
  • Inicialización de Variables:
  • Limpieza del Archivo de Log:
  • Inicio de Jobs en Segundo Plano:
  • Actualización de la Interfaz de Usuario:
  • Funcion $BDetener.Add_Click():

    
    $BDetener.Add_Click({
        $script:stopFlag = $true
        if ($null -ne $Global:script:job) {
            Stop-Job $Global:script:job
            Remove-Job $Global:script:job
            $Global:script:job = $null
        }
        if ($null -ne $Global:script:logJob) {
            Stop-Job $Global:script:logJob
            Remove-Job $Global:script:logJob
            $Global:script:logJob = $null
        }
        $startButton.Enabled = $true
        $BDetener.Enabled = $false
        $BFiltrarRojo.Enabled = $true
        $BMostrarTodo.Enabled = $true
    })
    
    
    ¡Copiado!
    Descripcion:Esta función asegura que todos los jobs en segundo plano se detengan y se eliminen correctamente, y actualiza la interfaz de usuario para reflejar que el proceso ha sido detenido.
  • Establece la bandera de parada:
  • Detiene y elimina el job principal:
  • Detiene y elimina el job de log:
  • Actualiza la interfaz de usuario:
  • Proposito:Leer y mostrar en tiempo real las entradas de un archivo de log.

    Funcion $BDetener.Add_Click():

    
    $BFiltrarRojo.Add_Click({
        $SalidaResultados.Clear()
        $logContent = Get-Content $TBArchivo.Text
        foreach ($line in $logContent) {
            if ($line -match "No se pudo establecer la conexión") {
                $SalidaResultados.SelectionStart = $SalidaResultados.TextLength
                $SalidaResultados.SelectionLength = 0
                $SalidaResultados.SelectionColor = [System.Drawing.Color]::Red
                $SalidaResultados.AppendText("$line`r`n")
            }
        }
        $SalidaResultados.ScrollToCaret()
    })
    
    
    ¡Copiado!
    Descripcion:Esta función filtra y resalta en rojo las líneas que contienen el mensaje "No se pudo establecer la conexión" en el control de salida, proporcionando una manera visual de identificar rápidamente los errores de conexión.
  • Limpia el contenido del control $SalidaResultados:
  • Itera sobre las líneas almacenadas en $script:allLines:
  • Filtra las líneas que contienen un mensaje específico:
  • Configura el color de selección y añade la línea al control de salida:
  • Desplaza el control de salida hasta el final:
  • Funcion $BMostrarTodo.Add_Click():

    
    $BMostrarTodo.Add_Click({
        $SalidaResultados.Clear()
        $logContent = Get-Content $TBArchivo.Text
        foreach ($line in $logContent) {
            $SalidaResultados.SelectionStart = $SalidaResultados.TextLength
            $SalidaResultados.SelectionLength = 0
            if ($line -match "No se pudo establecer la conexión") {
                $SalidaResultados.SelectionColor = [System.Drawing.Color]::Red
            } elseif ($line -match "Conexión exitosa") {
                $SalidaResultados.SelectionColor = [System.Drawing.Color]::Green
            } else {
                $SalidaResultados.SelectionColor = $SalidaResultados.ForeColor
            }
            $SalidaResultados.AppendText("$line`r`n")
        }
        $SalidaResultados.ScrollToCaret()
    })
    
    
    ¡Copiado!
    Descripcion:Esta función muestra todas las líneas almacenadas en $script:allLines, coloreando las líneas específicas según su contenido para resaltar errores de conexión en rojo y conexiones exitosas en verde.
  • Limpia el contenido del control $SalidaResultados:
  • Itera sobre las líneas almacenadas en $script:allLines:
  • Configura el color de selección y añade la línea al control de salida:
  • Desplaza el control de salida hasta el final:
  • Codigo completo:

    <#
    AUTOR: Vladimir Campos
    REQUISITOS
    Windows con PowerShell: El script está escrito en PowerShell, por lo que necesitas un sistema operativo Windows con PowerShell instalado. Windows 10 y 11 ya vienen con PowerShell preinstalado.
    PowerShell 5.1 o superior: Aunque debería funcionar en versiones anteriores, se recomienda usar PowerShell 5.1 o PowerShell 7 para una mejor compatibilidad y rendimiento.
    #>
    
    #Creado por Vladimir Campos
    Add-Type -AssemblyName System.Windows.Forms
    Add-Type -AssemblyName System.Drawing
    $timer = New-Object System.Windows.Forms.Timer
    $timer.Interval = 1000 
    
    $ImagenBytes = [Convert]::FromBase64String('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')
    $pictureBox.SizeMode = [System.Windows.Forms.PictureBoxSizeMode]::StretchImage
    $LPNG = "iVBORw0KGgoAAAANSUhEUgAAAMgAAAAuCAYAAABtRVYBAAAACXBIWXMAAAsTAAALEwEAmpwYAAAGq2lUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNy4xLWMwMDAgNzkuYTg3MzFiOSwgMjAyMS8wOS8wOS0wMDozNzozOCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczpzdEV2dD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlRXZlbnQjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIiB4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ9InhtcC5kaWQ6ODIxNzExM2UtNmZjNS0zNjQyLWIzMDctOGEzNDM3ZmY2NWRkIiB4bXBNTTpEb2N1bWVudElEPSJhZG9iZTpkb2NpZDpwaG90b3Nob3A6Mzk4YTY5ZDMtYzljYS0zYzRhLWE4YTctZjhmYmM2MmYxOWU0IiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjEzNDk3YzZlLWVjNTgtMzM0YS1hZWY2LWFhMWFlODRjNGE0YiIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgMjMuMCAoV2luZG93cykiIHhtcDpDcmVhdGVEYXRlPSIyMDI0LTExLTIwVDEzOjU2OjExLTA2OjAwIiB4bXA6TW9kaWZ5RGF0ZT0iMjAyNC0xMS0yMFQxNzo1MTo0My0wNjowMCIgeG1wOk1ldGFkYXRhRGF0ZT0iMjAyNC0xMS0yMFQxNzo1MTo0My0wNjowMCIgZGM6Zm9ybWF0PSJpbWFnZS9wbmciIHBob3Rvc2hvcDpDb2xvck1vZGU9IjMiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo4MjE3MTEzZS02ZmM1LTM2NDItYjMwNy04YTM0MzdmZjY1ZGQiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6ODIxNzExM2UtNmZjNS0zNjQyLWIzMDctOGEzNDM3ZmY2NWRkIi8+IDx4bXBNTTpIaXN0b3J5PiA8cmRmOlNlcT4gPHJkZjpsaSBzdEV2dDphY3Rpb249InNhdmVkIiBzdEV2dDppbnN0YW5jZUlEPSJ4bXAuaWlkOjQ4OTAyZGY4LTNjNzQtNzc0MC05YjM1LTBjYjkyODRjYTgyMCIgc3RFdnQ6d2hlbj0iMjAyNC0xMS0yMFQxNzo0NzoyMi0wNjowMCIgc3RFdnQ6c29mdHdhcmVBZ2VudD0iQWRvYmUgUGhvdG9zaG9wIDIzLjAgKFdpbmRvd3MpIiBzdEV2dDpjaGFuZ2VkPSIvIi8+IDxyZGY6bGkgc3RFdnQ6YWN0aW9uPSJzYXZlZCIgc3RFdnQ6aW5zdGFuY2VJRD0ieG1wLmlpZDoxMzQ5N2M2ZS1lYzU4LTMzNGEtYWVmNi1hYTFhZTg0YzRhNGIiIHN0RXZ0OndoZW49IjIwMjQtMTEtMjBUMTc6NTE6NDMtMDY6MDAiIHN0RXZ0OnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCAyMy4wIChXaW5kb3dzKSIgc3RFdnQ6Y2hhbmdlZD0iLyIvPiA8L3JkZjpTZXE+IDwveG1wTU06SGlzdG9yeT4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz55i9rdAAAuNUlEQVR4nO2deXyU1fnovzOTmclkZ0IC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"
    $lenbytes = [Convert]::FromBase64String($LPNG)
    $lenmemoria = New-Object System.IO.MemoryStream
    $lenmemoria.Write($lenbytes, 0, $lenbytes.Length)
    $lenmemoria.Position = 0
    $imagenl = [System.Drawing.Image]::FromStream($lenmemoria, $true)
    
    $ms = New-Object System.IO.MemoryStream(,$ImagenBytes)
    $image = [System.Drawing.Image]::FromStream($ms)
    $bitmap = New-Object System.Drawing.Bitmap($image)
    $iconHandle = $bitmap.GetHicon()
    $icon = [System.Drawing.Icon]::FromHandle($iconHandle)
    $image.Dispose()
    $bitmap.Dispose()
    
    #monitorea un puerto y registra resultados
    function CheckConeccion {
        param($targetHost, $port, $logFile)
        while ($true) {
            $startTime = [DateTime]::Now
            try {
                $tcpClient = New-Object System.Net.Sockets.TcpClient
                $tcpClient.ReceiveTimeout = 320
                $tcpClient.SendTimeout = 320
                $tcpClient.Connect($targetHost, $port)
                if ($tcpClient.Connected) {
                    $endTime = [DateTime]::Now
                    $responseTime = ($endTime - $startTime).TotalMilliseconds
                    $logMessage = "[$(Get-Date -Format "HH:mm:ss")] Conexión exitosa al puerto $port en $targetHost - Tiempo de respuesta: $responseTime ms"
                    Add-Content -Path $logFile -Value $logMessage
                    $tcpClient.Close()
                }
            } catch [System.Net.Sockets.SocketException] {
                $logMessage = "[$(Get-Date -Format "HH:mm:ss")] No se pudo establecer la conexión al puerto $port en $targetHost (error de socket)"
                Add-Content -Path $logFile -Value $logMessage
            } catch {
                $logMessage = "[$(Get-Date -Format "HH:mm:ss")] No se pudo establecer la conexión al puerto $port en $targetHost (error desconocido)"
                Add-Content -Path $logFile -Value $logMessage
            } finally {
                if ($null -ne $tcpClient) {
                    $tcpClient.Close()
                    $tcpClient = $null
                }
            }
            Start-Sleep -Seconds 2
            if ($script:stopFlag) { break }
        }
    }
    
    #actualiza la interfaz gráfica con nuevas líneas del log.
    function ReadLogFile {
        param($logFile)
        $lastPosition = 0
        while ($true) {
            if (Test-Path $logFile) {
                $fileContent = Get-Content $logFile -Raw
                if ($fileContent.Length -gt $lastPosition) {
                    $newContent = $fileContent.Substring($lastPosition)
                    $lastPosition = $fileContent.Length
                    Write-Output $newContent
                }
            }
            Start-Sleep -Milliseconds 500
            if ($script:stopFlag) { break }
        }
    }
    
    
    $Formulario = New-Object System.Windows.Forms.Form
    $Formulario.Text = "Monitor de Conexión"
    $Formulario.Size = New-Object System.Drawing.Size(800,600)
    $Formulario.Icon=$icon
    $Formulario.StartPosition = "CenterScreen"
    $Formulario.FormBorderStyle = 'FixedDialog'
    $Formulario.ControlBox = $false
    
    $pictureBox = New-Object System.Windows.Forms.PictureBox
    $pictureBox.Size = New-Object System.Drawing.Size(200, 40)
    $pictureBox.Location = New-Object System.Drawing.Point(10, 10)
    $pictureBox.Image = $imagenl
    
    $Formulario.Controls.Add($pictureBox)
    $LObjetivo = New-Object System.Windows.Forms.Label
    $LObjetivo.Location = New-Object System.Drawing.Point(240,23)
    $LObjetivo.Size = New-Object System.Drawing.Size(20,20)
    $LObjetivo.Text = "IP:"
    $Formulario.Controls.Add($LObjetivo)
    
    $TBObjetivo = New-Object System.Windows.Forms.TextBox
    $TBObjetivo.Location = New-Object System.Drawing.Point(260,20)
    $TBObjetivo.Size = New-Object System.Drawing.Size(150,20)
    $Formulario.Controls.Add($TBObjetivo)
    
    $LPuerto = New-Object System.Windows.Forms.Label
    $LPuerto.Location = New-Object System.Drawing.Point(430,20)
    $LPuerto.Size = New-Object System.Drawing.Size(45,23)
    $LPuerto.Text = "Puerto:"
    $Formulario.Controls.Add($LPuerto)
    
    $TBPuerto = New-Object System.Windows.Forms.TextBox
    $TBPuerto.Location = New-Object System.Drawing.Point(480,20)
    $TBPuerto.Size = New-Object System.Drawing.Size(50,20)
    $Formulario.Controls.Add($TBPuerto)
    
    $LArchivo = New-Object System.Windows.Forms.Label
    $LArchivo.Location = New-Object System.Drawing.Point(175,53)
    $LArchivo.Size = New-Object System.Drawing.Size(85,20)
    $LArchivo.Text = "Archivo de Log:"
    $Formulario.Controls.Add($LArchivo)
    
    $TBArchivo = New-Object System.Windows.Forms.TextBox
    $TBArchivo.Location = New-Object System.Drawing.Point(260,50)
    $TBArchivo.Size = New-Object System.Drawing.Size(270,20)
    $TBArchivo.Text = "error.log"
    $Formulario.Controls.Add($TBArchivo)
    
    $startButton = New-Object System.Windows.Forms.Button
    $startButton.Location = New-Object System.Drawing.Point(565,20)
    $startButton.Size = New-Object System.Drawing.Size(75,23)
    $startButton.Text = "Iniciar"
    $Formulario.Controls.Add($startButton)
    
    $BDetener = New-Object System.Windows.Forms.Button
    $BDetener.Location = New-Object System.Drawing.Point(665,20)
    $BDetener.Size = New-Object System.Drawing.Size(75,23)
    $BDetener.Text = "Detener"
    $BDetener.Enabled = $false
    $Formulario.Controls.Add($BDetener)
    
    $SalidaResultados = New-Object System.Windows.Forms.RichTextBox
    $SalidaResultados.Location = New-Object System.Drawing.Point(10,80)
    $SalidaResultados.Size = New-Object System.Drawing.Size(760,440)
    $SalidaResultados.MultiLine = $true
    $SalidaResultados.ScrollBars = "Vertical"
    $Formulario.Controls.Add($SalidaResultados)
    
    $BFiltrarRojo = New-Object System.Windows.Forms.Button
    $BFiltrarRojo.Location = New-Object System.Drawing.Point(10, 530)
    $BFiltrarRojo.Size = New-Object System.Drawing.Size(120, 23)
    $BFiltrarRojo.Text = "Mostrar solo errores"
    $BFiltrarRojo.Enabled = $false
    $Formulario.Controls.Add($BFiltrarRojo)
    
    $BMostrarTodo = New-Object System.Windows.Forms.Button
    $BMostrarTodo.Location = New-Object System.Drawing.Point(140, 530)
    $BMostrarTodo.Size = New-Object System.Drawing.Size(120, 23)
    $BMostrarTodo.Text = "Mostrar todo"
    $BMostrarTodo.Enabled = $false
    $Formulario.Controls.Add($BMostrarTodo)
    
    $BSalir = New-Object System.Windows.Forms.Button
    $BSalir.Location = New-Object System.Drawing.Point(665, 50)
    $BSalir.Size = New-Object System.Drawing.Size(75, 23)
    $BSalir.Text = "Salir"
    $Formulario.Controls.Add($BSalir)
    $BSalir.Add_Click({
        $Formulario.Close()
    })
    
    $script:stopFlag = $false
    $Global:script:job = $null
    $Global:script:logJob = $null
    $script:allLines = @()
    
    $startButton.Add_Click({
        # Validar entradas
        if ([string]::IsNullOrWhiteSpace($TBObjetivo.Text) -or [string]::IsNullOrWhiteSpace($TBPuerto.Text)) {
            [System.Windows.Forms.MessageBox]::Show("Debe ingresar una IP y un puerto válidos.", "Error", [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
            return
        }
        $script:stopFlag = $false
        $targetHost = $TBObjetivo.Text
        $port = [int]$TBPuerto.Text
        $logFile = $TBArchivo.Text
        if($targetHost -eq ""){}
        # Limpiar el archivo de log antes de comenzar
        Clear-Content -Path $logFile -ErrorAction SilentlyContinue
    
        $Global:script:job = Start-Job -ScriptBlock ${function:CheckConeccion} -ArgumentList $targetHost, $port, $logFile
        $Global:script:logJob = Start-Job -ScriptBlock ${function:ReadLogFile} -ArgumentList $logFile
        $startButton.Enabled = $false
        $BDetener.Enabled = $true
        
        # Limpiar la salida en la GUI
        $SalidaResultados.Clear()
        $script:allLines = @()
    })
    
    $BDetener.Add_Click({
        $script:stopFlag = $true
        if ($null -ne $Global:script:job) {
            Stop-Job $Global:script:job
            Remove-Job $Global:script:job
            $Global:script:job = $null
        }
        if ($null -ne $Global:script:logJob) {
            Stop-Job $Global:script:logJob
            Remove-Job $Global:script:logJob
            $Global:script:logJob = $null
        }
        $startButton.Enabled = $true
        $BDetener.Enabled = $false
        $BFiltrarRojo.Enabled = $true
        $BMostrarTodo.Enabled = $true
    })
    
    $BFiltrarRojo.Add_Click({
        $SalidaResultados.Clear()
        $logContent = Get-Content $TBArchivo.Text
        foreach ($line in $logContent) {
            if ($line -match "No se pudo establecer la conexión") {
                $SalidaResultados.SelectionStart = $SalidaResultados.TextLength
                $SalidaResultados.SelectionLength = 0
                $SalidaResultados.SelectionColor = [System.Drawing.Color]::Red
                $SalidaResultados.AppendText("$line`r`n")
            }
        }
        $SalidaResultados.ScrollToCaret()
    })
    
    $BMostrarTodo.Add_Click({
        $SalidaResultados.Clear()
        $logContent = Get-Content $TBArchivo.Text
        foreach ($line in $logContent) {
            $SalidaResultados.SelectionStart = $SalidaResultados.TextLength
            $SalidaResultados.SelectionLength = 0
            if ($line -match "No se pudo establecer la conexión") {
                $SalidaResultados.SelectionColor = [System.Drawing.Color]::Red
            } elseif ($line -match "Conexión exitosa") {
                $SalidaResultados.SelectionColor = [System.Drawing.Color]::Green
            } else {
                $SalidaResultados.SelectionColor = $SalidaResultados.ForeColor
            }
            $SalidaResultados.AppendText("$line`r`n")
        }
        $SalidaResultados.ScrollToCaret()
    })
    
    $timer.Add_Tick({
        if ($null -ne $Global:script:logJob) {
            $output = Receive-Job $Global:script:logJob
            if ($output) {
                $SalidaResultados.SuspendLayout()
                $SalidaResultados.SelectionStart = $SalidaResultados.TextLength
                $SalidaResultados.SelectionLength = 0
                
                foreach ($line in $output.Split("`n")) {
                    $line = $line.Trim()
                    if ($line -match "No se pudo establecer la conexión") {
                        $SalidaResultados.SelectionColor = [System.Drawing.Color]::Red
                    } elseif ($line -match "Conexión exitosa") {
                        $SalidaResultados.SelectionColor = [System.Drawing.Color]::Green
                    } else {
                        $SalidaResultados.SelectionColor = $SalidaResultados.ForeColor
                    }
                    $SalidaResultados.AppendText($line + "`r`n")
                }
                
                $SalidaResultados.ScrollToCaret()
                $SalidaResultados.ResumeLayout()
            }
        }
    })
    
    $timer.Start()
    
    $Formulario.ShowDialog(
    
    )
    
    if ($null -ne $Global:script:job) {
        Stop-Job $Global:script:job
        Remove-Job $Global:script:job
    }
    if ($null -ne $Global:script:logJob) {
        Stop-Job $Global:script:logJob
        Remove-Job $Global:script:logJob
    }
    
    ¡Copiado!
    Atras Inicio