<# Limpieza de Windows Herramientas BAIT · https://bait.cl/herramientas/script-limpieza/ Qué hace: 1. Mide el espacio libre del disco del sistema. 2. Borra los temporales del usuario y de Windows. 3. Vacía la caché de descargas de Windows Update (detiene y vuelve a iniciar el servicio). 4. Vacía la papelera de reciclaje (solo si respondes que sí). 5. Borra la caché de miniaturas y los informes de errores antiguos. 6. Opcional: limpieza de componentes de Windows con DISM (pregunta antes). 7. Vuelve a medir y muestra un resumen. Los archivos que estén en uso se saltan sin error. No toca documentos, descargas ni programas. Requiere administrador para limpiar las carpetas de Windows; si no lo es, ofrece abrirse de nuevo como administrador o limpiar solo lo del usuario. Uso: Clic derecho > Ejecutar con PowerShell o bien: powershell -ExecutionPolicy Bypass -File .\limpieza-windows.ps1 Parámetro opcional -SinPreguntas: no pregunta nada (no vacía la papelera ni ejecuta DISM). #> param( [switch]$SinPreguntas ) $ErrorActionPreference = 'Continue' $Host.UI.RawUI.WindowTitle = 'Limpieza de Windows (BAIT)' # ---------- utilidades ---------- function Test-Administrador { $id = [Security.Principal.WindowsIdentity]::GetCurrent() $principal = New-Object Security.Principal.WindowsPrincipal($id) return $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) } # Pregunta sí o no. Devuelve $true si la respuesta empieza con S. function Confirmar([string]$Texto) { if ($SinPreguntas) { return $false } $r = Read-Host "$Texto (S/N)" return ($r -match '^[sS]') } # Convierte bytes a un texto legible: 1,5 GB, 300 MB, etc. function Formato-Tamano([double]$Bytes) { if ($Bytes -ge 1GB) { return ('{0:N2} GB' -f ($Bytes / 1GB)) } if ($Bytes -ge 1MB) { return ('{0:N1} MB' -f ($Bytes / 1MB)) } if ($Bytes -ge 1KB) { return ('{0:N0} KB' -f ($Bytes / 1KB)) } return ('{0:N0} bytes' -f $Bytes) } function Espacio-Libre { $disco = Get-CimInstance -ClassName Win32_LogicalDisk -Filter "DeviceID='$env:SystemDrive'" return [double]$disco.FreeSpace } # Suma el tamaño de los archivos de una carpeta (o de un patrón de archivos). function Medir([string]$Ruta) { if (-not (Test-Path -LiteralPath $Ruta -ErrorAction SilentlyContinue) -and -not (Test-Path $Ruta -ErrorAction SilentlyContinue)) { return 0 } $suma = (Get-ChildItem -Path $Ruta -Recurse -Force -File -ErrorAction SilentlyContinue | Measure-Object -Property Length -Sum).Sum if ($suma) { return [double]$suma } else { return 0 } } # Resultados para el resumen final $resumen = New-Object System.Collections.Generic.List[object] # Borra el contenido de una carpeta (no la carpeta misma) y anota cuánto liberó. function Limpiar-Carpeta([string]$Ruta, [string]$Descripcion) { if (-not (Test-Path -LiteralPath $Ruta)) { $resumen.Add([pscustomobject]@{ Item = $Descripcion; Liberado = 0; Nota = 'No existe' }) return } Write-Host " Limpiando $Descripcion..." -ForegroundColor Gray $antes = Medir $Ruta Get-ChildItem -LiteralPath $Ruta -Force -ErrorAction SilentlyContinue | ForEach-Object { Remove-Item -LiteralPath $_.FullName -Recurse -Force -ErrorAction SilentlyContinue } $despues = Medir $Ruta $liberado = [math]::Max(0, $antes - $despues) $nota = '' if ($despues -gt 0) { $nota = 'Quedaron archivos en uso' } $resumen.Add([pscustomobject]@{ Item = $Descripcion; Liberado = $liberado; Nota = $nota }) } # ---------- permisos ---------- $esAdmin = Test-Administrador if (-not $esAdmin) { Write-Host '' Write-Host 'No estás ejecutando como administrador.' -ForegroundColor Yellow Write-Host 'Sin permisos solo se pueden limpiar los temporales de tu usuario.' if ($PSCommandPath -and (Confirmar '¿Quieres abrir el script de nuevo como administrador?')) { $argumentos = @('-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', "`"$PSCommandPath`"") if ($SinPreguntas) { $argumentos += '-SinPreguntas' } Start-Process -FilePath 'powershell.exe' -ArgumentList $argumentos -Verb RunAs exit } Write-Host 'Seguimos solo con lo de tu usuario.' -ForegroundColor Yellow } # ---------- inicio ---------- Write-Host '' Write-Host '=== Limpieza de Windows ===' -ForegroundColor Cyan Write-Host "Equipo: $env:COMPUTERNAME Usuario: $env:USERNAME" $libreAntes = Espacio-Libre Write-Host ("Espacio libre en {0} antes de empezar: {1}" -f $env:SystemDrive, (Formato-Tamano $libreAntes)) Write-Host '' if (-not $SinPreguntas) { if (-not (Confirmar 'Se borrarán archivos temporales. Cierra los programas abiertos. ¿Continuar?')) { Write-Host 'Cancelado. No se borró nada.' Read-Host 'Presiona Enter para cerrar' exit } } # 1. Temporales del usuario Write-Host '1. Temporales' -ForegroundColor Cyan Limpiar-Carpeta $env:TEMP 'Temporales de tu usuario' # 2. Temporales de Windows (requiere administrador) if ($esAdmin) { Limpiar-Carpeta (Join-Path $env:windir 'Temp') 'Temporales de Windows' } # 3. Caché de Windows Update: hay que detener el servicio para poder borrarla if ($esAdmin) { Write-Host '2. Caché de Windows Update' -ForegroundColor Cyan $servicio = Get-Service -Name wuauserv -ErrorAction SilentlyContinue $estabaCorriendo = $servicio -and $servicio.Status -eq 'Running' try { if ($estabaCorriendo) { Write-Host ' Deteniendo el servicio Windows Update...' -ForegroundColor Gray Stop-Service -Name wuauserv -Force -ErrorAction Stop } Limpiar-Carpeta (Join-Path $env:windir 'SoftwareDistribution\Download') 'Descargas de Windows Update' } catch { Write-Host " No se pudo detener Windows Update: $($_.Exception.Message)" -ForegroundColor Yellow } finally { # Siempre se vuelve a iniciar, aunque algo falle if ($estabaCorriendo) { Start-Service -Name wuauserv -ErrorAction SilentlyContinue Write-Host ' Servicio Windows Update iniciado de nuevo.' -ForegroundColor Gray } } } # 4. Papelera de reciclaje: lo que se borra de ahí no se puede recuperar, por eso se pregunta Write-Host '3. Papelera de reciclaje' -ForegroundColor Cyan if (Confirmar ' Vaciar la papelera borra para siempre lo que hay en ella. ¿Vaciarla?') { $antesPapelera = Espacio-Libre try { Clear-RecycleBin -Force -ErrorAction Stop } catch { # Clear-RecycleBin falla si la papelera ya está vacía; no es un problema } $resumen.Add([pscustomobject]@{ Item = 'Papelera de reciclaje'; Liberado = [math]::Max(0, (Espacio-Libre) - $antesPapelera); Nota = '' }) } else { $resumen.Add([pscustomobject]@{ Item = 'Papelera de reciclaje'; Liberado = 0; Nota = 'No se vació' }) } # 5. Miniaturas: Windows las vuelve a crear cuando hacen falta Write-Host '4. Miniaturas e informes de errores' -ForegroundColor Cyan $carpetaMiniaturas = Join-Path $env:LOCALAPPDATA 'Microsoft\Windows\Explorer' $antesMini = Medir (Join-Path $carpetaMiniaturas 'thumbcache_*.db') Get-ChildItem -Path $carpetaMiniaturas -Filter 'thumbcache_*.db' -Force -ErrorAction SilentlyContinue | Remove-Item -Force -ErrorAction SilentlyContinue $despuesMini = Medir (Join-Path $carpetaMiniaturas 'thumbcache_*.db') $notaMini = '' if ($despuesMini -gt 0) { $notaMini = 'El Explorador usa algunas; se liberan al reiniciar' } $resumen.Add([pscustomobject]@{ Item = 'Caché de miniaturas'; Liberado = [math]::Max(0, $antesMini - $despuesMini); Nota = $notaMini }) # 6. Informes de errores de Windows (WER) Limpiar-Carpeta (Join-Path $env:LOCALAPPDATA 'Microsoft\Windows\WER') 'Informes de errores de tu usuario' if ($esAdmin) { Limpiar-Carpeta (Join-Path $env:ProgramData 'Microsoft\Windows\WER\ReportArchive') 'Informes de errores archivados' Limpiar-Carpeta (Join-Path $env:ProgramData 'Microsoft\Windows\WER\ReportQueue') 'Informes de errores en cola' } # 7. DISM: limpia versiones antiguas de componentes. Tarda varios minutos y no se puede deshacer if ($esAdmin) { Write-Host '5. Limpieza de componentes (DISM)' -ForegroundColor Cyan Write-Host ' Quita versiones antiguas de actualizaciones ya instaladas. Puede tardar de 5 a 20 minutos.' Write-Host ' Después no podrás desinstalar esas actualizaciones antiguas.' if (Confirmar ' ¿Ejecutar la limpieza de componentes?') { $antesDism = Espacio-Libre & "$env:windir\System32\Dism.exe" /Online /Cleanup-Image /StartComponentCleanup $resumen.Add([pscustomobject]@{ Item = 'Componentes de Windows (DISM)'; Liberado = [math]::Max(0, (Espacio-Libre) - $antesDism); Nota = '' }) } } # ---------- resumen ---------- $libreDespues = Espacio-Libre $total = [math]::Max(0, $libreDespues - $libreAntes) Write-Host '' Write-Host '=== Resumen ===' -ForegroundColor Cyan foreach ($r in $resumen) { $linea = '{0,-38} {1,12}' -f $r.Item, (Formato-Tamano $r.Liberado) if ($r.Nota) { $linea += " ($($r.Nota))" } Write-Host $linea } Write-Host '' Write-Host ("Espacio libre antes: {0}" -f (Formato-Tamano $libreAntes)) Write-Host ("Espacio libre después: {0}" -f (Formato-Tamano $libreDespues)) Write-Host ("Total liberado: {0}" -f (Formato-Tamano $total)) -ForegroundColor Green if (-not $esAdmin) { Write-Host 'Como administrador se puede liberar más espacio (Windows Update, temporales del sistema y DISM).' -ForegroundColor Yellow } Write-Host '' Write-Host '¿Tu equipo sigue lento? En BAIT lo revisamos por ti: https://bait.cl' if (-not $SinPreguntas) { Read-Host 'Presiona Enter para cerrar' }