USB técnico multiherramienta 2026: Ventoy, Sergei Strelec, Rescuezilla y más

En este video te muestro cómo reunir en un solo USB técnico herramientas para trabajar tanto en equipos que no inician Windows como en computadoras que sí arrancan, pero necesitan diagnóstico, recuperación, mantenimiento u optimización.

Aquí tienes los enlaces de las principales herramientas que aparecen en el video y, más abajo, los 6 scripts KAMBIG para PowerShell listos para abrir, copiar y pegar.

Importante: KAMBIG no vende memorias USB con estas herramientas. Los programas de terceros se descargan desde sus respectivas páginas.

¿Qué puedes hacer con este USB técnico?

Cuando Windows no inicia

Arrancar entornos de rescate, revisar discos y particiones, recuperar información, clonar unidades o disponer de medios de instalación.

Cuando Windows sí inicia

Ejecutar aplicaciones portables, revisar hardware, analizar el almacenamiento, diagnosticar el inicio y realizar tareas de mantenimiento.

Herramientas y enlaces

Ventoy

La base del USB multiherramienta. Permite arrancar diferentes imágenes ISO desde un mismo dispositivo.

Descargar Ventoy
Sergei Strelec WinPE

Entorno WinPE con numerosas herramientas para diagnóstico, rescate, discos, particiones y mantenimiento.

Visitar Sergei Strelec
SystemRescue

Distribución Linux de rescate para trabajar con discos, particiones, sistemas de archivos y recuperación.

Descargar SystemRescue
Rescuezilla

Herramienta gráfica orientada principalmente a clonación, creación de imágenes y restauración de discos.

Descargar Rescuezilla
Windows 11

ISO oficial de Microsoft para instalación y tareas relacionadas con recuperación del sistema.

Descargar Windows 11
PortableApps

Permite llevar y ejecutar aplicaciones portables directamente desde el USB.

Descargar PortableApps
Winhance

Herramienta gráfica para configuración, personalización, administración y optimización de Windows.

Visitar Winhance
WinUtil de Chris Titus Tech

Utilidad basada en PowerShell para aplicaciones, ajustes y diferentes tareas de administración de Windows.

Ver WinUtil

Scripts KAMBIG para PowerShell

Estos scripts están pensados como herramientas de consulta y diagnóstico. Haz clic sobre cualquiera para ver el código completo y utilizar el botón Copiar script.

Consejo: revisa siempre el contenido antes de ejecutar un script y abre PowerShell con los permisos adecuados cuando sea necesario.

Script 1 · Diagnóstico de memoria RAM Memoria instalada, tipo, ranuras, fabricante, modelo y velocidad.
$ram=@(Get-CimInstance Win32_PhysicalMemory);$arr=@(Get-CimInstance Win32_PhysicalMemoryArray);$total=[math]::Round((($ram|Measure-Object Capacity -Sum).Sum/1GB),0);$slots=($arr|Measure-Object MemoryDevices -Sum).Sum;$usados=$ram.Count;$libres=if($slots){$slots-$usados}else{"No informado"};$slotsTexto=if($slots){$slots}else{"No informado"};$map=@{20="DDR";21="DDR2";24="DDR3";26="DDR4";34="DDR5"};$cod=[int]$ram[0].SMBIOSMemoryType;$tipo=$map[$cod];if(-not $tipo){$tipo="No identificado ($cod)"};Write-Host "`n===== INFORME DE MEMORIA RAM =====`n" -ForegroundColor Cyan;Write-Host "Memoria instalada : $total GB";Write-Host "Tipo de memoria : $tipo";Write-Host "Ranuras utilizadas : $usados de $slotsTexto";Write-Host "Ranuras disponibles: $libres`n";$ram|ForEach-Object{$modelo=if($_.PartNumber){$_.PartNumber.Trim()}else{"No informado"};$marca=if($_.Manufacturer){$_.Manufacturer.Trim()}else{"No informado"};[PSCustomObject]@{Ranura=$_.DeviceLocator;GB=[math]::Round($_.Capacity/1GB,0);Marca=$marca;Modelo=$modelo;Reportada=$_.Speed;Configurada=$_.ConfiguredClockSpeed}}|Format-Table -AutoSize
Script 2 · Discos y espacio disponible Discos físicos, tipo, conexión, capacidad, estado y espacio libre.
$ErrorActionPreference="SilentlyContinue";$discos=@(Get-PhysicalDisk|Sort-Object DeviceId);$volumenes=@(Get-Volume|Where-Object DriveLetter -ne $null);$datos=@(foreach($disco in $discos){$conexion=if($disco.BusType){[string]$disco.BusType}else{"No informado"};$medio=if($disco.MediaType){[string]$disco.MediaType}else{""};$tipo=if($conexion -eq "NVMe"){"SSD NVMe"}elseif($medio -eq "SSD"){"SSD"}elseif($medio -eq "HDD"){"HDD"}else{"No identificado"};$saludOriginal=[string]$disco.HealthStatus;$salud=if($saludOriginal -eq "Healthy"){"Correcto"}elseif($saludOriginal -eq "Warning"){"Advertencia"}elseif($saludOriginal -eq "Unhealthy"){"Con problemas"}else{"No informado"};$modelo=if($disco.FriendlyName){$disco.FriendlyName}else{"No informado"};[PSCustomObject]@{Disco=$disco.DeviceId;Tipo=$tipo;Conexion=$conexion;Capacidad="$([math]::Round($disco.Size/1GB,1)) GB";Estado=$salud;Modelo=$modelo}});$unidades=@(foreach($volumen in ($volumenes|Sort-Object DriveLetter)){$total=[math]::Round($volumen.Size/1GB,1);$libre=[math]::Round($volumen.SizeRemaining/1GB,1);$porcentaje=if($volumen.Size -gt 0){[math]::Round(($volumen.SizeRemaining/$volumen.Size)*100,0)}else{0};$estado=if($porcentaje -lt 15){"ESPACIO BAJO"}else{"Correcto"};[PSCustomObject]@{Unidad="$($volumen.DriveLetter):";Nombre=if($volumen.FileSystemLabel){$volumen.FileSystemLabel}else{"Sin nombre"};Total="$total GB";Libre="$libre GB";Disponible="$porcentaje %";Estado=$estado}});Clear-Host;Write-Host "";Write-Host "===== INFORME DE ALMACENAMIENTO =====" -ForegroundColor Cyan;Write-Host "";$datos|Format-Table -AutoSize;Write-Host "===== ESPACIO DE LAS UNIDADES =====" -ForegroundColor Cyan;Write-Host "";$unidades|Format-Table -AutoSize;if($unidades.Estado -contains "ESPACIO BAJO"){Write-Host "";Write-Host "ADVERTENCIA: Hay una unidad con menos del 15 % de espacio disponible." -ForegroundColor Yellow;Write-Host ""}
Script 3 · Procesador, tarjeta madre y BIOS Procesador, placa base, BIOS, UEFI/Legacy, Secure Boot y TPM.
& {
$ErrorActionPreference = "SilentlyContinue"

function Obtener-Texto {
    param(
        $Valor,
        $Alternativo = "No informado"
    )

    if ([string]::IsNullOrWhiteSpace([string]$Valor)) {
        return $Alternativo
    }

    return (([string]$Valor -replace "\s+", " ").Trim())
}

function Convertir-SiNo {
    param($Valor)

    if ($null -eq $Valor) {
        return "No informado"
    }

    if ([bool]$Valor) {
        return "Sí"
    }

    return "No"
}

function Obtener-FechaBIOS {
    param($Fecha)

    if (-not $Fecha) {
        return $null
    }

    try {
        if ($Fecha -is [datetime]) {
            return [datetime]$Fecha
        }

        return [Management.ManagementDateTimeConverter]::ToDateTime(
            [string]$Fecha
        )
    }
    catch {
        try {
            return [datetime]$Fecha
        }
        catch {
            return $null
        }
    }
}

function Obtener-TipoFirmware {
    try {
        if (-not ("KambigFirmware" -as [type])) {
            Add-Type @"
using System.Runtime.InteropServices;

public static class KambigFirmware
{
    [DllImport("kernel32.dll")]
    public static extern bool GetFirmwareType(out uint firmwareType);
}
"@
        }

        [uint32]$tipo = 0

        if ([KambigFirmware]::GetFirmwareType([ref]$tipo)) {
            if ($tipo -eq 2) {
                return "UEFI"
            }

            if ($tipo -eq 1) {
                return "BIOS heredado (Legacy)"
            }
        }
    }
    catch {}

    return "No identificado"
}

# CONSULTA DEL PROCESADOR, PLACA BASE Y BIOS

$procesadores = @(Get-CimInstance -ClassName Win32_Processor)
$procesador = $procesadores | Select-Object -First 1

$placa = Get-CimInstance -ClassName Win32_BaseBoard |
    Select-Object -First 1

$bios = Get-CimInstance -ClassName Win32_BIOS |
    Select-Object -First 1

if (-not $procesador) {
    Write-Host ""
    Write-Host "    No se pudo obtener la información del procesador." `
        -ForegroundColor Red
    Write-Host ""
    return
}

# PROCESADOR

$nombreProcesador = Obtener-Texto $procesador.Name
$socketProcesador = Obtener-Texto $procesador.SocketDesignation

$nucleosTotales = (
    $procesadores |
    Measure-Object -Property NumberOfCores -Sum
).Sum

$logicosTotales = (
    $procesadores |
    Measure-Object -Property NumberOfLogicalProcessors -Sum
).Sum

$usoCalculado = (
    $procesadores |
    Measure-Object -Property LoadPercentage -Average
).Average

if ($null -ne $usoCalculado) {
    $usoProcesador = "$([math]::Round($usoCalculado, 0)) %"
}
else {
    $usoProcesador = "No informado"
}

if ($procesador.MaxClockSpeed) {
    $frecuenciaNominal = "{0:N2} GHz" -f (
        $procesador.MaxClockSpeed / 1000
    )
}
else {
    $frecuenciaNominal = "No informada"
}

# PLACA BASE

$fabricantePlaca = Obtener-Texto $placa.Manufacturer
$modeloPlaca = Obtener-Texto $placa.Product
$versionPlaca = Obtener-Texto $placa.Version

# BIOS

$fabricanteBIOS = Obtener-Texto $bios.Manufacturer
$versionBIOS = Obtener-Texto $bios.SMBIOSBIOSVersion
$fechaBIOSObjeto = Obtener-FechaBIOS $bios.ReleaseDate

if ($fechaBIOSObjeto) {
    $fechaBIOS = $fechaBIOSObjeto.ToString("dd/MM/yyyy")

    $antiguedadBIOS = [math]::Floor(
        ((Get-Date) - $fechaBIOSObjeto).TotalDays / 365.25
    )
}
else {
    $fechaBIOS = "No informada"
    $antiguedadBIOS = $null
}

# TIPO DE FIRMWARE Y SECURE BOOT

$tipoFirmware = Obtener-TipoFirmware
$secureBoot = "No se pudo comprobar"

if ($tipoFirmware -eq "UEFI") {
    try {
        $valorSecureBoot = (
            Get-ItemProperty `
                -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\State" `
                -Name UEFISecureBootEnabled `
                -ErrorAction Stop
        ).UEFISecureBootEnabled

        if ($valorSecureBoot -eq 1) {
            $secureBoot = "Activado"
        }
        else {
            $secureBoot = "Desactivado"
        }
    }
    catch {
        try {
            if (Confirm-SecureBootUEFI -ErrorAction Stop) {
                $secureBoot = "Activado"
            }
            else {
                $secureBoot = "Desactivado"
            }
        }
        catch {
            $secureBoot = "No se pudo comprobar"
        }
    }
}
elseif ($tipoFirmware -like "BIOS heredado*") {
    $secureBoot = "No disponible en modo Legacy"
}

# TPM

$tpmCim = $null
$tpmComando = $null

try {
    $tpmCim = Get-CimInstance `
        -Namespace "Root\CIMV2\Security\MicrosoftTpm" `
        -ClassName Win32_Tpm `
        -ErrorAction Stop |
        Select-Object -First 1
}
catch {}

if (Get-Command Get-Tpm -ErrorAction SilentlyContinue) {
    try {
        $tpmComando = Get-Tpm -ErrorAction Stop
    }
    catch {}
}

$tpmPresente = "No detectado"
$versionTPM = "No disponible"
$tpmPreparado = "No disponible"

if (
    $tpmCim -or
    ($tpmComando -and $tpmComando.TpmPresent)
) {
    $tpmPresente = "Sí"

    if ($tpmCim -and $tpmCim.SpecVersion) {
        $versionTPM = (
            ([string]$tpmCim.SpecVersion -split ",")[0]
        ).Trim()
    }
    else {
        $versionTPM = "No informada"
    }

    if ($tpmComando) {
        $tpmPreparado = Convertir-SiNo $tpmComando.TpmReady
    }
    else {
        $tpmPreparado = "No se pudo comprobar"
    }
}

# ANÁLISIS

$avisos = @()

if (
    $null -ne $antiguedadBIOS -and
    $antiguedadBIOS -ge 5
) {
    $avisos += "El BIOS tiene cinco años o más. Revisa si existe una actualización."
}

if ($tipoFirmware -like "BIOS heredado*") {
    $avisos += "El sistema está iniciando mediante BIOS heredado."
}

if ($tpmPresente -ne "Sí") {
    $avisos += "No se detectó un módulo TPM."
}
elseif ($versionTPM -notmatch "^2\.0") {
    $avisos += "No se pudo confirmar que el equipo utilice TPM 2.0."
}

# PRESENTACIÓN DE LOS RESULTADOS

$margen = "    "
$linea = $margen + ("=" * 62)
$sublinea = $margen + ("-" * 62)

Write-Host ""
Write-Host $linea -ForegroundColor Cyan
Write-Host "${margen}DIAGNÓSTICO DE PROCESADOR, PLACA BASE Y BIOS" `
    -ForegroundColor Cyan
Write-Host $linea -ForegroundColor Cyan

Write-Host ""
Write-Host "${margen}PROCESADOR" -ForegroundColor Yellow
Write-Host $sublinea
Write-Host "${margen}Modelo                  : $nombreProcesador"
Write-Host "${margen}Socket                  : $socketProcesador"
Write-Host "${margen}Núcleos físicos         : $nucleosTotales"
Write-Host "${margen}Procesadores lógicos    : $logicosTotales"
Write-Host "${margen}Frecuencia nominal      : $frecuenciaNominal"
Write-Host "${margen}Uso actual              : $usoProcesador"

Write-Host ""
Write-Host "${margen}PLACA BASE" -ForegroundColor Yellow
Write-Host $sublinea
Write-Host "${margen}Fabricante              : $fabricantePlaca"
Write-Host "${margen}Modelo                  : $modeloPlaca"
Write-Host "${margen}Versión                 : $versionPlaca"

Write-Host ""
Write-Host "${margen}BIOS Y FIRMWARE" -ForegroundColor Yellow
Write-Host $sublinea
Write-Host "${margen}Fabricante              : $fabricanteBIOS"
Write-Host "${margen}Versión                 : $versionBIOS"
Write-Host "${margen}Fecha de publicación    : $fechaBIOS"
Write-Host "${margen}Modo de arranque        : $tipoFirmware"
Write-Host "${margen}Secure Boot             : $secureBoot"

Write-Host ""
Write-Host "${margen}TPM" -ForegroundColor Yellow
Write-Host $sublinea
Write-Host "${margen}TPM detectado           : $tpmPresente"
Write-Host "${margen}Versión principal       : $versionTPM"
Write-Host "${margen}Preparado para usarse   : $tpmPreparado"

Write-Host ""
Write-Host "${margen}RESULTADO" -ForegroundColor Yellow
Write-Host $sublinea

if ($avisos.Count -eq 0) {
    Write-Host "${margen}[OK] No se detectaron avisos en los datos revisados." `
        -ForegroundColor Green
}
else {
    foreach ($aviso in $avisos) {
        Write-Host "${margen}[AVISO] $aviso" `
            -ForegroundColor Yellow
    }
}

Write-Host ""
Write-Host "${margen}Este script solamente consulta información del equipo."
Write-Host "${margen}No modifica Windows, el BIOS ni ninguna configuración."

Write-Host ""
Write-Host "${margen}Desarrollado por Allan Montero" `
    -ForegroundColor Cyan
Write-Host "${margen}KAMBIG Centro de Estudios | www.kambig.com" `
    -ForegroundColor Cyan

Write-Host $linea -ForegroundColor Cyan
Write-Host ""
}
Script 4 · Diagnóstico de fallas de Windows Apagados, reinicios, pantallas azules, errores de hardware y aplicaciones.
# ============================================================
# KAMBIG - SCRIPT #4
# DIAGNOSTICO DE FALLAS DE WINDOWS
# Windows 10 / Windows 11
# SOLO LECTURA - NO MODIFICA EL SISTEMA
# ============================================================

Clear-Host

$Dias  = 14
$Desde = (Get-Date).AddDays(-$Dias)
$M     = "   "

function Get-Eventos {
    param(
        [string]$Log,
        [string]$Proveedor,
        [int]$Id = 0
    )

    try {
        $Filtro = @{
            LogName      = $Log
            StartTime    = $Desde
            ProviderName = $Proveedor
        }

        if ($Id -gt 0) {
            $Filtro["Id"] = $Id
        }

        return @(
            Get-WinEvent -FilterHashtable $Filtro `
                -ErrorAction SilentlyContinue
        )
    }
    catch {
        return @()
    }
}

function Get-DatosEvento {
    param($Evento)

    $Datos = @{}

    try {
        [xml]$Xml = $Evento.ToXml()

        foreach ($Dato in $Xml.Event.EventData.Data) {
            $Nombre = [string]$Dato.Name
            $Valor  = [string]$Dato.'#text'

            if (-not [string]::IsNullOrWhiteSpace($Nombre)) {
                $Datos[$Nombre] = $Valor
            }
        }
    }
    catch {}

    return $Datos
}

function Fecha {
    param($Valor)

    if ($null -eq $Valor) {
        return "-"
    }

    return $Valor.ToString("dd/MM/yyyy HH:mm:ss")
}

# ------------------------------------------------------------
# ESTADO ACTUAL
# ------------------------------------------------------------

try {
    $SO = Get-CimInstance Win32_OperatingSystem `
        -ErrorAction SilentlyContinue

    $UltimoInicio = $SO.LastBootUpTime
    $Uptime = (Get-Date) - $UltimoInicio

    $TiempoEncendido = "{0} d {1} h {2} min" -f `
        $Uptime.Days,
        $Uptime.Hours,
        $Uptime.Minutes
}
catch {
    $UltimoInicio = $null
    $TiempoEncendido = "No disponible"
}

# ------------------------------------------------------------
# EVENTOS
# ------------------------------------------------------------

$Kernel41 = Get-Eventos `
    "System" `
    "Microsoft-Windows-Kernel-Power" `
    41

$Apagados6008 = Get-Eventos `
    "System" `
    "EventLog" `
    6008

$BugChecks = Get-Eventos `
    "System" `
    "Microsoft-Windows-WER-SystemErrorReporting" `
    1001

$TodosWHEA = Get-Eventos `
    "System" `
    "Microsoft-Windows-WHEA-Logger"

$WHEARelevantes = @(
    $TodosWHEA | Where-Object {
        $_.Level -ge 1 -and $_.Level -le 3
    }
)

$Cuelgues = Get-Eventos `
    "Application" `
    "Application Hang" `
    1002

$FallosApp = Get-Eventos `
    "Application" `
    "Application Error" `
    1000

# ------------------------------------------------------------
# ULTIMO FALLO DE APLICACION
# ------------------------------------------------------------

$NombreUltimaApp = $null
$ModuloUltimaApp = $null

if ($FallosApp.Count -gt 0) {

    $UltimoFallo = $FallosApp |
        Sort-Object TimeCreated -Descending |
        Select-Object -First 1

    $DatosFallo = Get-DatosEvento $UltimoFallo

    if ($DatosFallo.ContainsKey("AppName")) {
        $NombreUltimaApp = $DatosFallo["AppName"]
    }

    if ($DatosFallo.ContainsKey("ModuleName")) {
        $ModuloUltimaApp = $DatosFallo["ModuleName"]
    }
}

# ------------------------------------------------------------
# TOP 3 APLICACIONES CON MAS FALLOS
# ------------------------------------------------------------

$ListaAppsFallos = @()

foreach ($Evento in $FallosApp) {

    $Datos = Get-DatosEvento $Evento

    if (
        $Datos.ContainsKey("AppName") -and
        -not [string]::IsNullOrWhiteSpace($Datos["AppName"])
    ) {
        $ListaAppsFallos += $Datos["AppName"]
    }
}

$TopApps = @(
    $ListaAppsFallos |
        Group-Object |
        Sort-Object Count -Descending |
        Select-Object -First 3
)

# ------------------------------------------------------------
# CABECERA
# ------------------------------------------------------------

Write-Host ""

Write-Host ($M + "============================================================") `
    -ForegroundColor Cyan

Write-Host ($M + "                 KAMBIG - SCRIPT #4") `
    -ForegroundColor Cyan

Write-Host ($M + "           DIAGNOSTICO DE FALLAS DE WINDOWS")

Write-Host ($M + "============================================================") `
    -ForegroundColor Cyan

Write-Host ""

Write-Host ($M + "Periodo analizado : Ultimos $Dias dias")
Write-Host ($M + "Ultimo inicio     : $(Fecha $UltimoInicio)")
Write-Host ($M + "Tiempo encendido  : $TiempoEncendido")

# ------------------------------------------------------------
# APAGADOS Y REINICIOS
# ------------------------------------------------------------

Write-Host ""
Write-Host ($M + "APAGADOS Y REINICIOS") `
    -ForegroundColor Cyan

Write-Host ($M + "------------------------------------------------------------")

if (
    ($Kernel41.Count -eq 0) -and
    ($Apagados6008.Count -eq 0)
) {

    Write-Host ($M + "[OK] No se detectaron apagados o reinicios inesperados.") `
        -ForegroundColor Green
}

if (
    ($Kernel41.Count -gt 0) -or
    ($Apagados6008.Count -gt 0)
) {

    $EventosApagado = @(
        $Kernel41
        $Apagados6008
    ) | Sort-Object TimeCreated -Descending

    $UltimoIncidente = $EventosApagado |
        Select-Object -First 1

    Write-Host ($M + "[ATENCION] Se detectaron registros de apagado o reinicio anormal.") `
        -ForegroundColor Yellow

    Write-Host ($M + "Ultimo registro : $(Fecha $UltimoIncidente.TimeCreated)") `
        -ForegroundColor Yellow
}

# ------------------------------------------------------------
# PANTALLAS AZULES
# ------------------------------------------------------------

Write-Host ""
Write-Host ($M + "PANTALLAS AZULES") `
    -ForegroundColor Cyan

Write-Host ($M + "------------------------------------------------------------")

if ($BugChecks.Count -eq 0) {

    Write-Host ($M + "[OK] No se encontraron pantallas azules registradas.") `
        -ForegroundColor Green
}

if ($BugChecks.Count -gt 0) {

    Write-Host ($M + "[REVISAR] Pantallas azules registradas: $($BugChecks.Count)") `
        -ForegroundColor Red

    $UltimoBug = $BugChecks |
        Sort-Object TimeCreated -Descending |
        Select-Object -First 1

    Write-Host ($M + "Ultimo registro : $(Fecha $UltimoBug.TimeCreated)") `
        -ForegroundColor Yellow
}

# ------------------------------------------------------------
# POSIBLES ERRORES DE HARDWARE
# ------------------------------------------------------------

Write-Host ""
Write-Host ($M + "POSIBLES ERRORES DE HARDWARE") `
    -ForegroundColor Cyan

Write-Host ($M + "------------------------------------------------------------")

if ($WHEARelevantes.Count -eq 0) {

    Write-Host ($M + "[OK] No se detectaron errores relevantes.") `
        -ForegroundColor Green
}

if ($WHEARelevantes.Count -gt 0) {

    Write-Host ($M + "[REVISAR] Windows registro $($WHEARelevantes.Count) eventos que requieren revision.") `
        -ForegroundColor Red
}

# ------------------------------------------------------------
# CUELGUES
# ------------------------------------------------------------

Write-Host ""
Write-Host ($M + "APLICACIONES COLGADAS") `
    -ForegroundColor Cyan

Write-Host ($M + "------------------------------------------------------------")

if ($Cuelgues.Count -eq 0) {

    Write-Host ($M + "[OK] No se encontraron aplicaciones colgadas.") `
        -ForegroundColor Green
}

if ($Cuelgues.Count -gt 0) {

    $UltimoCuelgue = $Cuelgues |
        Sort-Object TimeCreated -Descending |
        Select-Object -First 1

    $DatosCuelgue = Get-DatosEvento $UltimoCuelgue

    Write-Host ($M + "[ATENCION] Aplicaciones colgadas: $($Cuelgues.Count)") `
        -ForegroundColor Yellow

    if ($DatosCuelgue.ContainsKey("AppName")) {

        Write-Host ($M + "Ultima aplicacion : $($DatosCuelgue['AppName'])") `
            -ForegroundColor Yellow
    }
}

# ------------------------------------------------------------
# FALLOS DE APLICACIONES
# ------------------------------------------------------------

Write-Host ""
Write-Host ($M + "FALLOS DE APLICACIONES") `
    -ForegroundColor Cyan

Write-Host ($M + "------------------------------------------------------------")

if ($FallosApp.Count -eq 0) {

    Write-Host ($M + "[OK] No se encontraron fallos de aplicaciones.") `
        -ForegroundColor Green
}

if ($FallosApp.Count -gt 0) {

    Write-Host ($M + "Fallos registrados : $($FallosApp.Count)") `
        -ForegroundColor Yellow

    if ($NombreUltimaApp) {

        Write-Host ($M + "Ultima aplicacion  : $NombreUltimaApp") `
            -ForegroundColor Yellow
    }

    if ($ModuloUltimaApp) {

        Write-Host ($M + "Modulo relacionado : $ModuloUltimaApp")
    }

    if ($TopApps.Count -gt 0) {

        Write-Host ""
        Write-Host ($M + "APLICACIONES CON MAS FALLOS") `
            -ForegroundColor Cyan

        foreach ($App in $TopApps) {

            $Linea = "{0,-30} : {1}" -f `
                $App.Name,
                $App.Count

            Write-Host ($M + $Linea) `
                -ForegroundColor Yellow
        }
    }
}

# ------------------------------------------------------------
# RESUMEN
# ------------------------------------------------------------

Write-Host ""

Write-Host ($M + "============================================================") `
    -ForegroundColor DarkGray

Write-Host ($M + "RESUMEN DEL DIAGNOSTICO") `
    -ForegroundColor Cyan

Write-Host ($M + "============================================================") `
    -ForegroundColor DarkGray

Write-Host ""

Write-Host ($M + "Apagados/Reinicios    : $([Math]::Max($Kernel41.Count,$Apagados6008.Count))")
Write-Host ($M + "Pantallas azules      : $($BugChecks.Count)")
Write-Host ($M + "Alertas de hardware   : $($WHEARelevantes.Count)")
Write-Host ($M + "Aplicaciones colgadas : $($Cuelgues.Count)")
Write-Host ($M + "Fallos aplicaciones   : $($FallosApp.Count)")

Write-Host ""

# ------------------------------------------------------------
# ESTADO GENERAL
# ------------------------------------------------------------

$FallaGrave = (
    ($BugChecks.Count -gt 0) -or
    ($WHEARelevantes.Count -gt 0)
)

$FallaImportante = (
    ($Kernel41.Count -gt 0) -or
    ($Apagados6008.Count -gt 0) -or
    ($Cuelgues.Count -gt 0)
)

if ($FallaGrave) {

    Write-Host ($M + "ESTADO GENERAL: REVISAR") `
        -ForegroundColor Red

    Write-Host ""

    Write-Host ($M + "Windows registro eventos que requieren un diagnostico") `
        -ForegroundColor Yellow

    Write-Host ($M + "mas detallado antes de determinar la causa.")
}

if (
    (-not $FallaGrave) -and
    $FallaImportante
) {

    Write-Host ($M + "ESTADO GENERAL: ATENCION") `
        -ForegroundColor Yellow

    Write-Host ""

    Write-Host ($M + "Windows registro fallas que conviene revisar.")
}

if (
    (-not $FallaGrave) -and
    (-not $FallaImportante)
) {

    Write-Host ($M + "ESTADO GENERAL: SIN FALLAS GRAVES REGISTRADAS") `
        -ForegroundColor Green

    if ($FallosApp.Count -gt 0) {

        Write-Host ""
        Write-Host ($M + "OBSERVACION: Se encontraron fallos de aplicaciones,") `
            -ForegroundColor Yellow

        Write-Host ($M + "pero esto no indica por si solo una falla general de Windows.")
    }
}

# ------------------------------------------------------------
# FINAL
# ------------------------------------------------------------

Write-Host ""

Write-Host ($M + "============================================================") `
    -ForegroundColor Cyan

Write-Host ($M + "KAMBIG Centro de Estudios") `
    -ForegroundColor Cyan

Write-Host ($M + "Diagnostico preliminar - No realiza cambios en Windows.")
Write-Host ($M + "Este resultado es orientativo y no identifica por si solo")
Write-Host ($M + "la causa exacta de una falla.")

Write-Host ($M + "============================================================") `
    -ForegroundColor Cyan

Write-Host ""
Write-Host ($M + "Presiona ENTER para finalizar...") `
    -ForegroundColor Yellow

[void](Read-Host)
Script 5 · Diagnóstico del inicio de Windows Tiempo de arranque, disco del sistema y programas de inicio.
Clear-Host

Write-Host "============================================================" -ForegroundColor Cyan
Write-Host "       KAMBIG - ANALISIS DE INICIO DE WINDOWS" -ForegroundColor Cyan
Write-Host "============================================================" -ForegroundColor Cyan

# ============================================================
# INICIO DEL SISTEMA
# ============================================================

Write-Host ""
Write-Host "INICIO DEL SISTEMA" -ForegroundColor Cyan
Write-Host "------------------------------------------------------------"

$os = Get-CimInstance Win32_OperatingSystem
$ultimoArranque = $os.LastBootUpTime

Write-Host "[i]  Ultimo arranque: $($ultimoArranque.ToString('dd/MM/yyyy HH:mm'))" -ForegroundColor Gray


# ============================================================
# DISCO DEL SISTEMA
# ============================================================

$tipoDisco = "No identificado"
$modeloDisco = "No identificado"

try {

    $particionSistema = Get-Partition -DriveLetter C -ErrorAction Stop
    $discoSistema = Get-Disk -Number $particionSistema.DiskNumber -ErrorAction Stop

    $modeloDisco = $discoSistema.FriendlyName

    if ($discoSistema.BusType -eq "NVMe") {
        $tipoDisco = "SSD NVMe"
    }

    if ($discoSistema.BusType -ne "NVMe") {

        $fisico = Get-PhysicalDisk -ErrorAction SilentlyContinue |
            Where-Object { $_.FriendlyName -eq $discoSistema.FriendlyName } |
            Select-Object -First 1

        if ($fisico.MediaType -eq "SSD") {
            $tipoDisco = "SSD"
        }

        if (($fisico.MediaType -eq "SSD") -and ($discoSistema.BusType -eq "SATA")) {
            $tipoDisco = "SSD SATA"
        }

        if ($fisico.MediaType -eq "HDD") {
            $tipoDisco = "Disco duro HDD"
        }
    }

    Write-Host "[i]  Disco del sistema: $tipoDisco" -ForegroundColor Gray
    Write-Host "[i]  Modelo: $modeloDisco" -ForegroundColor Gray

}
catch {

    Write-Host "[i]  No fue posible identificar el disco del sistema." -ForegroundColor Gray

}


# ============================================================
# TIEMPO DE ARRANQUE
# ============================================================

$tiempoArranque = $null

try {

    $evento = Get-WinEvent -FilterHashtable @{
        LogName = "Microsoft-Windows-Diagnostics-Performance/Operational"
        Id      = 100
    } -MaxEvents 1 -ErrorAction Stop

    $xml = [xml]$evento.ToXml()

    foreach ($dato in $xml.Event.EventData.Data) {

        if ($dato.Name -eq "BootTime") {
            $tiempoArranque = [math]::Round(([double]$dato.'#text' / 1000),1)
        }
    }

}
catch {

    $tiempoArranque = $null

}

if ($null -eq $tiempoArranque) {
    Write-Host "[i]  No fue posible medir el tiempo de inicio." -ForegroundColor Gray
}

if (($null -ne $tiempoArranque) -and ($tiempoArranque -lt 30)) {
    Write-Host "[OK] Tiempo de inicio: $tiempoArranque segundos." -ForegroundColor Green
}

if (($null -ne $tiempoArranque) -and ($tiempoArranque -ge 30) -and ($tiempoArranque -lt 60)) {
    Write-Host "[i]  Tiempo de inicio: $tiempoArranque segundos." -ForegroundColor Yellow
}

if (($null -ne $tiempoArranque) -and ($tiempoArranque -ge 60)) {
    Write-Host "[!]  Inicio lento: $tiempoArranque segundos." -ForegroundColor Red
}


# ============================================================
# PROGRAMAS DE INICIO
# ============================================================

Write-Host ""
Write-Host "PROGRAMAS QUE INICIAN CON WINDOWS" -ForegroundColor Cyan
Write-Host "------------------------------------------------------------"

$inicio = @(
    Get-CimInstance Win32_StartupCommand |
    Sort-Object Name -Unique
)

$revisar = @()

foreach ($programa in $inicio) {

    $nombre = $programa.Name
    $descripcion = "No identificado"
    $estado = "REVISAR"

    if ($nombre -like "SecurityHealth*") {
        $descripcion = "Seguridad de Windows"
        $estado = "OK"
    }

    if ($nombre -like "RtkAudUService*") {
        $descripcion = "Servicio de audio Realtek"
        $estado = "OK"
    }

    if ($nombre -eq "OneDrive") {
        $descripcion = "Sincronizacion de archivos"
        $estado = "INFO"
    }

    if ($nombre -like "OneDriveSetup*") {
        $descripcion = "Configuracion de Microsoft OneDrive"
        $estado = "INFO"
    }

    if ($nombre -like "NVIDIA Broadcast*") {
        $descripcion = "Aplicacion NVIDIA Broadcast"
        $estado = "INFO"
    }

    if ($nombre -like "Everything*") {
        $descripcion = "Buscador de archivos Everything"
        $estado = "INFO"
    }

    if ($nombre -like "Reflect*") {
        $descripcion = "Software Macrium Reflect"
        $estado = "INFO"
    }

    if ($nombre -like "Speech Recognition*") {
        $descripcion = "Reconocimiento de voz de Windows"
        $estado = "INFO"
    }

    if ($nombre -like "kpm.exe*") {
        $descripcion = "Kaspersky Password Manager"
        $estado = "INFO"
    }


    if ($estado -eq "OK") {

        Write-Host "[OK] " -ForegroundColor Green -NoNewline
        Write-Host ("{0,-25} {1}" -f $nombre,$descripcion)

    }

    if ($estado -eq "INFO") {

        Write-Host "[i]  " -ForegroundColor Gray -NoNewline
        Write-Host ("{0,-25} {1}" -f $nombre,$descripcion)

    }

    if ($estado -eq "REVISAR") {

        Write-Host "[?]  " -ForegroundColor Yellow -NoNewline
        Write-Host ("{0,-25} {1}" -f $nombre,$descripcion)

        $ruta = $programa.Command

        if ([string]::IsNullOrWhiteSpace($ruta)) {
            $ruta = "Ubicacion no disponible"
        }

        $revisar += [PSCustomObject]@{
            Nombre = $nombre
            Ruta   = $ruta
        }
    }
}

Write-Host ""
Write-Host "[i]  Total: $($inicio.Count) programas configurados para iniciar." -ForegroundColor Gray


# ============================================================
# DIAGNOSTICO
# ============================================================

Write-Host ""
Write-Host "============================================================" -ForegroundColor Cyan
Write-Host "DIAGNOSTICO" -ForegroundColor Cyan
Write-Host "============================================================" -ForegroundColor Cyan

if ($tipoDisco -ne "No identificado") {
    Write-Host "[OK] Disco del sistema: $tipoDisco" -ForegroundColor Green
}

if (($null -ne $tiempoArranque) -and ($tiempoArranque -lt 30)) {
    Write-Host "[OK] Inicio de Windows: $tiempoArranque segundos" -ForegroundColor Green
}

if (($null -ne $tiempoArranque) -and ($tiempoArranque -ge 30) -and ($tiempoArranque -lt 60)) {
    Write-Host "[i]  Inicio de Windows: $tiempoArranque segundos" -ForegroundColor Yellow
}

if (($null -ne $tiempoArranque) -and ($tiempoArranque -ge 60)) {
    Write-Host "[!]  Inicio de Windows: $tiempoArranque segundos" -ForegroundColor Red
}

if ($inicio.Count -lt 10) {
    Write-Host "[OK] $($inicio.Count) programas configurados al inicio" -ForegroundColor Green
}

if (($inicio.Count -ge 10) -and ($inicio.Count -lt 15)) {
    Write-Host "[i]  $($inicio.Count) programas configurados al inicio" -ForegroundColor Yellow
}

if ($inicio.Count -ge 15) {
    Write-Host "[!]  $($inicio.Count) programas configurados al inicio" -ForegroundColor Red
}

if ($revisar.Count -eq 0) {
    Write-Host "[OK] No se detectaron elementos desconocidos" -ForegroundColor Green
}

if ($revisar.Count -gt 0) {
    Write-Host "[!]  Se detectaron $($revisar.Count) elementos para revisar" -ForegroundColor Yellow
}


# ============================================================
# ELEMENTOS DESCONOCIDOS
# ============================================================

if ($revisar.Count -gt 0) {

    Write-Host ""
    Write-Host "ELEMENTOS PARA REVISAR" -ForegroundColor Yellow
    Write-Host "------------------------------------------------------------"

    foreach ($elemento in $revisar) {

        Write-Host "[?] $($elemento.Nombre)" -ForegroundColor Yellow
        Write-Host "    Ubicacion: $($elemento.Ruta)" -ForegroundColor Gray
        Write-Host ""

    }

    Write-Host "Verifica estos elementos antes de desactivarlos." -ForegroundColor Gray

}


# ============================================================
# RESULTADO FINAL
# ============================================================

$problemas = 0

if (($null -ne $tiempoArranque) -and ($tiempoArranque -ge 60)) {
    $problemas++
}

if ($inicio.Count -ge 15) {
    $problemas++
}

if ($revisar.Count -gt 0) {
    $problemas++
}


Write-Host ""
Write-Host "RESULTADO" -ForegroundColor Cyan
Write-Host "------------------------------------------------------------"

if ($problemas -eq 0) {
    Write-Host "[OK] Inicio del sistema sin problemas evidentes." -ForegroundColor Green
}

if ($problemas -gt 0) {
    Write-Host "[!]  Se encontraron puntos que conviene revisar." -ForegroundColor Yellow
}


# ============================================================
# FINAL
# ============================================================

Write-Host ""
Write-Host "============================================================"
Write-Host "El script solo analiza. No modifica ninguna configuracion." -ForegroundColor Green
Write-Host ""

Read-Host "Presiona ENTER para finalizar"
Script 6 · Archivos que más espacio ocupan Localiza archivos grandes y ayuda a revisar el uso del almacenamiento.
& {
# ============================================================
# KAMBIG Centro de Estudios
# SCRIPT #6: Encuentra los archivos que mas espacio ocupan
# Solo lectura: NO elimina, mueve, modifica ni envia archivos.
# ============================================================

function Mostrar-Tamano([uint64]$bytes) {
    if ($bytes -ge 1TB) { return ('{0:N2} TB' -f ($bytes / 1TB)) }
    if ($bytes -ge 1GB) { return ('{0:N2} GB' -f ($bytes / 1GB)) }
    if ($bytes -ge 1MB) { return ('{0:N2} MB' -f ($bytes / 1MB)) }
    if ($bytes -ge 1KB) { return ('{0:N2} KB' -f ($bytes / 1KB)) }
    return "$bytes bytes"
}

function Clasificar-Archivo([string]$rutaCompleta) {
    $r = $rutaCompleta.ToLowerInvariant()
    $perfil = $env:USERPROFILE.ToLowerInvariant()
    $nombre = [System.IO.Path]::GetFileName($r)
    $extension = [System.IO.Path]::GetExtension($r)

    if ($r -match '\.(vdi|vhd|vhdx|vmdk)$' -or $r -match '\\virtualbox vms\\|\\vmware\\') {
        return 'MAQUINA VIRTUAL - NO BORRAR SIN REVISAR'
    }
    if ($r -match '\\temp\\|\\cache\\|\\caches\\|\\proxy files\\' -or $r.EndsWith('.tmp')) {
        return 'TEMPORAL/CACHE - REVISAR'
    }
    if ($nombre -in @('pagefile.sys','hiberfil.sys','swapfile.sys','memory.dmp') -or $r -match '^.:\\windows\\|^.:\\program files\\|^.:\\program files \(x86\)\\|\\system volume information\\|\\recovery\\') {
        return 'SISTEMA - NO BORRAR MANUALMENTE'
    }
    if ($r -match '\\appdata\\|^.:\\programdata\\') {
        return 'DESCONOCIDO - INVESTIGAR'
    }
    if ($extension -in @('.mp4','.mov','.mkv','.avi','.m4v','.mp3','.wav','.jpg','.jpeg','.png','.iso','.zip','.rar','.7z') -or $r.StartsWith($perfil) -or $r -match '\\desktop\\|\\documents\\|\\downloads\\|\\videos\\') {
        return 'PERSONAL - REVISAR'
    }
    return 'DESCONOCIDO - INVESTIGAR'
}

function Categoria-Corta([string]$clasificacion) {
    if ($clasificacion -like 'PERSONAL*') { return 'PERSONAL' }
    if ($clasificacion -like 'TEMPORAL*') { return 'TEMPORAL' }
    if ($clasificacion -like 'SISTEMA*') { return 'SISTEMA' }
    if ($clasificacion -like 'MAQUINA*') { return 'VM' }
    return 'OTRO'
}

function Color-Categoria([string]$clasificacion) {
    if ($clasificacion -like 'PERSONAL*') { return 'Green' }
    if ($clasificacion -like 'TEMPORAL*') { return 'Yellow' }
    if ($clasificacion -like 'SISTEMA*') { return 'Red' }
    if ($clasificacion -like 'MAQUINA*') { return 'Magenta' }
    return 'DarkYellow'
}

function Acortar([string]$texto, [int]$maximo) {
    if ([string]::IsNullOrWhiteSpace($texto)) { return '(sin nombre)' }
    if ($texto.Length -le $maximo) { return $texto }
    return $texto.Substring(0, $maximo - 3) + '...'
}

# Margen visual aplicado a toda la salida en PowerShell.
$margen = '  '

Clear-Host
Write-Host ($margen + '============================================================') -ForegroundColor DarkCyan
Write-Host ($margen + 'KAMBIG - ARCHIVOS QUE MAS ESPACIO OCUPAN') -ForegroundColor Cyan
Write-Host ($margen + '============================================================') -ForegroundColor DarkCyan
Write-Host ($margen + 'Este script es de solo lectura y permite mostrar los 10, 25') -ForegroundColor Green
Write-Host ($margen + 'o 50 archivos mas grandes de la unidad o carpeta elegida.') -ForegroundColor Green
Write-Host ''
Write-Host ($margen + 'IMPORTANTE: analizar una unidad completa puede tardar varios minutos.') -ForegroundColor Yellow
Write-Host ($margen + 'No compartas capturas sin revisar nombres y rutas personales.') -ForegroundColor Yellow
Write-Host ''

$ruta = Read-Host ($margen + 'Escribe la unidad o carpeta (ENTER para analizar C:\)')
if ([string]::IsNullOrWhiteSpace($ruta)) { $ruta = 'C:\' }
$ruta = $ruta.Trim().Trim('"')
if ($ruta -match '^[A-Za-z]$') { $ruta = $ruta + ':\' }
elseif ($ruta -match '^[A-Za-z]:$') { $ruta = $ruta + '\' }

if (-not (Test-Path -LiteralPath $ruta -PathType Container)) {
    Write-Host ("`n" + $margen + 'La ruta indicada no existe o no es una carpeta.') -ForegroundColor Red
    Write-Host ($margen + 'Ejemplos validos: C:\   D:\   C:\Users\Allan\Downloads') -ForegroundColor DarkGray
    return
}

$respuestaCantidad = Read-Host ($margen + 'Cuantos resultados quieres ver: 10, 25 o 50 (ENTER para 25)')
switch ($respuestaCantidad) {
    '10' { $cantidad = 10 }
    '50' { $cantidad = 50 }
    default { $cantidad = 25 }
}

Write-Host ("`n" + $margen + "Analizando: $ruta") -ForegroundColor Cyan
Write-Host ($margen + 'Espera hasta que aparezcan los resultados...') -ForegroundColor Yellow

$inicio = Get-Date
$totalArchivos = 0
[uint64]$bytesAnalizados = 0
$mayores = @()
$destinoSimulado = Join-Path $env:TEMP 'KAMBIG_ANALISIS_SIN_COPIA'

# Robocopy se utiliza en modo /L: solo enumera; no copia ningun archivo.
& robocopy.exe $ruta $destinoSimulado /L /S /BYTES /FP /NJH /NJS /NDL /NC /XJ /R:0 /W:0 2>$null |
ForEach-Object {
    if ($_ -match '^\s*(\d+)\s+(.+)$') {
        [uint64]$tamano = $matches[1]
        $archivo = $matches[2].Trim()

        if ($archivo -and -not $archivo.EndsWith('\')) {
            $totalArchivos++
            $bytesAnalizados += $tamano
            $mayores += [pscustomobject][ordered]@{
                Bytes     = $tamano
                Archivo   = [System.IO.Path]::GetFileName($archivo)
                Ubicacion = [System.IO.Path]::GetDirectoryName($archivo)
                RutaCompleta = $archivo
            }

            # Mantiene una lista pequena para evitar consumir demasiada memoria.
            if ($mayores.Count -ge 200) {
                $mayores = @($mayores | Sort-Object Bytes -Descending | Select-Object -First $cantidad)
            }

            if (($totalArchivos % 5000) -eq 0) {
                Write-Progress -Activity 'Buscando archivos grandes' -Status ("{0:N0} archivos revisados" -f $totalArchivos)
            }
        }
    }
}

Write-Progress -Activity 'Buscando archivos grandes' -Completed
$mayores = @($mayores | Sort-Object Bytes -Descending | Select-Object -First $cantidad)
$duracion = (Get-Date) - $inicio

if ($mayores.Count -eq 0) {
    Write-Host ("`n" + $margen + 'No se encontraron archivos o Windows no permitio acceder a la ruta.') -ForegroundColor Red
    Write-Host ($margen + 'Prueba abriendo PowerShell como administrador.') -ForegroundColor Yellow
    return
}

foreach ($item in $mayores) {
    $item | Add-Member -NotePropertyName Clasificacion -NotePropertyValue (Clasificar-Archivo $item.RutaCompleta) -Force
}

$personales = @($mayores | Where-Object { $_.Clasificacion -like 'PERSONAL*' }).Count
$temporales = @($mayores | Where-Object { $_.Clasificacion -like 'TEMPORAL*' }).Count
$sistema = @($mayores | Where-Object { $_.Clasificacion -like 'SISTEMA*' }).Count
$virtuales = @($mayores | Where-Object { $_.Clasificacion -like 'MAQUINA*' }).Count
$otros = $mayores.Count - $personales - $temporales - $sistema - $virtuales

Clear-Host
Write-Host ($margen + '============================================================') -ForegroundColor DarkCyan
Write-Host ($margen + 'KAMBIG - RESUMEN DEL ANALISIS') -ForegroundColor Cyan
Write-Host ($margen + '============================================================') -ForegroundColor DarkCyan
Write-Host ($margen + ("Ruta analizada: {0}" -f $ruta)) -ForegroundColor White
Write-Host ($margen + ("Archivos revisados: {0:N0}" -f $totalArchivos)) -ForegroundColor White
Write-Host ($margen + ("Tamano total contabilizado (estimado): {0}" -f (Mostrar-Tamano $bytesAnalizados))) -ForegroundColor White
Write-Host ($margen + ("Tiempo: {0} min {1} s" -f [math]::Floor($duracion.TotalMinutes),$duracion.Seconds)) -ForegroundColor White
Write-Host ($margen + ("Resultados mostrados: {0}" -f $mayores.Count)) -ForegroundColor White
Write-Host ''
Write-Host ($margen + ("PERSONALES: {0}" -f $personales)) -NoNewline -ForegroundColor Green
Write-Host ("    TEMPORALES: {0}" -f $temporales) -ForegroundColor Yellow
Write-Host ($margen + ("SISTEMA:    {0}" -f $sistema)) -NoNewline -ForegroundColor Red
Write-Host ("    MAQUINAS VIRTUALES: {0}" -f $virtuales) -ForegroundColor Magenta
Write-Host ($margen + ("OTROS:      {0}" -f $otros)) -ForegroundColor DarkYellow
Write-Host ''

Write-Host ($margen + '============================================================') -ForegroundColor DarkCyan
Write-Host ($margen + 'ARCHIVOS MAS GRANDES') -ForegroundColor Cyan
Write-Host ($margen + '============================================================') -ForegroundColor DarkCyan
Write-Host ($margen + ('{0,-4}{1,-12}{2,-11}{3,-22}{4}' -f 'No.','TAMANO','CATEGORIA','PROPORCION','ARCHIVO')) -ForegroundColor White
Write-Host ($margen + ('-' * 92)) -ForegroundColor DarkGray

$mayorTamano = [double]$mayores[0].Bytes
if ($mayorTamano -le 0) { $mayorTamano = 1 }

for ($i = 0; $i -lt $mayores.Count; $i++) {
    $item = $mayores[$i]
    $bloques = [math]::Max(1, [math]::Round(([double]$item.Bytes / $mayorTamano) * 18))
    $barra = ([string][char]0x2588) * $bloques
    $categoria = Categoria-Corta $item.Clasificacion
    $color = Color-Categoria $item.Clasificacion
    $nombre = Acortar $item.Archivo 38
    Write-Host ($margen + ('{0,-4}{1,-12}' -f ($i + 1),(Mostrar-Tamano $item.Bytes))) -NoNewline -ForegroundColor White
    Write-Host ('{0,-11}' -f $categoria) -NoNewline -ForegroundColor $color
    Write-Host ('{0,-22}' -f $barra) -NoNewline -ForegroundColor $color
    Write-Host $nombre -ForegroundColor White
}

Write-Host ''
Write-Host ($margen + 'ADVERTENCIA:') -ForegroundColor Red
Write-Host ($margen + 'Un archivo grande no necesariamente puede eliminarse.') -ForegroundColor Yellow
Write-Host ($margen + 'No borres archivos de Windows o de programas sin comprobar su funcion.') -ForegroundColor Yellow
Write-Host ($margen + 'Este resultado no se guarda ni se envia a ningun lugar.') -ForegroundColor Green

Write-Host ''
$abrir = Read-Host ($margen + 'Escribe un numero para ver los detalles y abrir su ubicacion (ENTER para salir)')
$numero = 0
if ([int]::TryParse($abrir, [ref]$numero) -and $numero -ge 1 -and $numero -le $mayores.Count) {
    $seleccionado = $mayores[$numero - 1]
    Write-Host ("`n" + $margen + "DETALLES DEL ARCHIVO #$numero") -ForegroundColor Cyan
    Write-Host ($margen + ("Tamano:        {0}" -f (Mostrar-Tamano $seleccionado.Bytes))) -ForegroundColor White
    Write-Host ($margen + ("Archivo:       {0}" -f $seleccionado.Archivo)) -ForegroundColor White
    Write-Host ($margen + ("Ubicacion:     {0}" -f $seleccionado.Ubicacion)) -ForegroundColor Gray
    Write-Host ($margen + ("Clasificacion: {0}" -f $seleccionado.Clasificacion)) -ForegroundColor (Color-Categoria $seleccionado.Clasificacion)
    $argumento = '/select,"{0}"' -f $seleccionado.RutaCompleta
    Start-Process -FilePath 'explorer.exe' -ArgumentList $argumento
} elseif (-not [string]::IsNullOrWhiteSpace($abrir)) {
    Write-Host ($margen + 'El numero indicado no es valido.') -ForegroundColor Red
}
}

¿Quieres aprender a utilizar estas herramientas en casos reales?

Tener las herramientas ayuda, pero lo importante es saber cuándo utilizarlas, cómo interpretar los resultados y qué procedimiento aplicar en cada falla.

Preguntas frecuentes

¿Puedo tener varias ISO en el mismo USB?

Sí. Ventoy permite mantener varias imágenes compatibles dentro del mismo dispositivo y elegir cuál iniciar desde su menú.

¿Estas herramientas sirven si Windows no inicia?

Varias sí. Sergei Strelec, SystemRescue y Rescuezilla pueden arrancar independientemente del Windows instalado.

¿Los scripts KAMBIG reparan automáticamente Windows?

No. Su función principal es consultar información y ayudar en un diagnóstico preliminar. El técnico debe interpretar los resultados antes de realizar cambios.

Pon a prueba tus conocimientos

Si ya trabajas con computadoras, prueba qué decisiones tomarías frente a diferentes situaciones de diagnóstico.