diff --git a/cleanup-windows.ps1 b/cleanup-windows.ps1 new file mode 100644 index 0000000..7f339a0 --- /dev/null +++ b/cleanup-windows.ps1 @@ -0,0 +1,160 @@ +# ════════════════════════════════════════════════════════════════ +# ARIA — Windows / WSL2 / Docker Desktop VHDX Cleanup +# ════════════════════════════════════════════════════════════════ +# +# Findet alle WSL2 + Docker Desktop ext4.vhdx Files unter +# C:\Users\\AppData\Local\... und kompaktiert sie via diskpart. +# Damit bekommst du Speicherplatz zurueck den du IN den Distros/ +# Containern geloescht hast (z.B. nach `docker system prune`), +# der aber von der VHDX bisher nicht freigegeben wurde. +# +# Nutzung (PowerShell als ADMIN): +# .\cleanup-windows.ps1 stefan +# .\cleanup-windows.ps1 -User stefan +# .\cleanup-windows.ps1 -User stefan -SkipPrune # nur compacten +# +# Was passiert: +# 1. Erst (optional): docker system prune + builder prune in WSL2 +# 2. wsl --shutdown +# 3. Alle gefundenen .vhdx Files mit diskpart compact vdisk shrinken +# +# Hinweis: diskpart braucht KEINE Hyper-V Tools (anders als Optimize-VHD). +# ════════════════════════════════════════════════════════════════ + +[CmdletBinding()] +param( + [Parameter(Mandatory=$true, Position=0, + HelpMessage="Dein Windows-Benutzername (z.B. stefan)")] + [string]$User, + + [Parameter(HelpMessage="Docker prune ueberspringen — nur compacten")] + [switch]$SkipPrune, + + [Parameter(HelpMessage="Docker prune NUR machen, dann beenden")] + [switch]$PruneOnly +) + +# Admin-Check +$isAdmin = ([Security.Principal.WindowsPrincipal] ` + [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole( + [Security.Principal.WindowsBuiltInRole]::Administrator) +if (-not $isAdmin) { + Write-Host "❌ Dieses Script muss als Administrator laufen." -ForegroundColor Red + Write-Host " Rechtsklick auf PowerShell → 'Als Administrator ausfuehren'" -ForegroundColor Yellow + exit 1 +} + +$basePath = "C:\Users\$User\AppData\Local" +if (-not (Test-Path $basePath)) { + Write-Host "❌ Pfad existiert nicht: $basePath" -ForegroundColor Red + Write-Host " Pruefe den Benutzernamen." -ForegroundColor Yellow + exit 1 +} + +Write-Host "════════════════════════════════════════════════════════════" -ForegroundColor Cyan +Write-Host " ARIA Cleanup fuer User: $User" -ForegroundColor Cyan +Write-Host "════════════════════════════════════════════════════════════" -ForegroundColor Cyan +Write-Host "" + +# ── 1. Docker prune (in WSL2) ────────────────────────────────── +if (-not $SkipPrune) { + Write-Host "[1/3] Docker Cleanup in WSL2..." -ForegroundColor Yellow + Write-Host " docker system prune -a --volumes -f" -ForegroundColor Gray + Write-Host " docker builder prune -a -f" -ForegroundColor Gray + Write-Host "" + try { + wsl -e bash -c "docker system prune -a --volumes -f && docker builder prune -a -f" + Write-Host " ✅ fertig" -ForegroundColor Green + } catch { + Write-Host " ⚠️ Docker prune fehlgeschlagen (vielleicht laeuft Docker Desktop nicht?)" -ForegroundColor Yellow + Write-Host " $_" -ForegroundColor Gray + } + Write-Host "" + if ($PruneOnly) { + Write-Host "─PruneOnly gesetzt — fertig." -ForegroundColor Cyan + exit 0 + } +} + +# ── 2. WSL2 shutdown ────────────────────────────────────────── +Write-Host "[2/3] WSL2 herunterfahren..." -ForegroundColor Yellow +wsl --shutdown +Start-Sleep -Seconds 3 +Write-Host " ✅ fertig" -ForegroundColor Green +Write-Host "" + +# ── 3. VHDX-Files finden + compacten ────────────────────────── +Write-Host "[3/3] VHDX-Files suchen + compacten..." -ForegroundColor Yellow +Write-Host "" + +$vhdxFiles = @() +$vhdxFiles += Get-ChildItem -Path "$basePath\Docker" -Recurse -Filter "*.vhdx" -ErrorAction SilentlyContinue +$vhdxFiles += Get-ChildItem -Path "$basePath\Packages" -Recurse -Filter "ext4.vhdx" -ErrorAction SilentlyContinue +$vhdxFiles = $vhdxFiles | Sort-Object FullName -Unique + +if ($vhdxFiles.Count -eq 0) { + Write-Host " Keine .vhdx Files gefunden." -ForegroundColor Yellow + exit 0 +} + +Write-Host "Gefundene Files (vorher):" -ForegroundColor Cyan +foreach ($f in $vhdxFiles) { + $sizeGB = [math]::Round($f.Length / 1GB, 2) + Write-Host (" {0,8} GB {1}" -f $sizeGB, $f.FullName) -ForegroundColor Gray +} +Write-Host "" + +$totalBefore = ($vhdxFiles | Measure-Object Length -Sum).Sum + +foreach ($f in $vhdxFiles) { + Write-Host "→ Compact: $($f.FullName)" -ForegroundColor White + $sizeBefore = [math]::Round($f.Length / 1GB, 2) + + # Temporaeres diskpart-Script schreiben + $tmp = [System.IO.Path]::GetTempFileName() + @" +select vdisk file="$($f.FullName)" +attach vdisk readonly +compact vdisk +detach vdisk +exit +"@ | Out-File -Encoding ASCII -FilePath $tmp + + try { + $output = & diskpart /s $tmp 2>&1 + # Datei neu lesen — Length ist gecacht + $newFile = Get-Item $f.FullName + $sizeAfter = [math]::Round($newFile.Length / 1GB, 2) + $saved = [math]::Round($sizeBefore - $sizeAfter, 2) + if ($saved -gt 0) { + Write-Host (" ✅ {0} GB → {1} GB (gespart: {2} GB)" -f $sizeBefore, $sizeAfter, $saved) -ForegroundColor Green + } else { + Write-Host (" ─ {0} GB → {1} GB (nichts zu holen — File war schon optimal)" -f $sizeBefore, $sizeAfter) -ForegroundColor DarkGray + } + } catch { + Write-Host " ❌ Fehler: $_" -ForegroundColor Red + Write-Host " diskpart-Output:" -ForegroundColor DarkGray + $output | ForEach-Object { Write-Host " $_" -ForegroundColor DarkGray } + } finally { + Remove-Item $tmp -ErrorAction SilentlyContinue + } + Write-Host "" +} + +# ── Zusammenfassung ───────────────────────────────────────── +$vhdxFilesAfter = @() +$vhdxFilesAfter += Get-ChildItem -Path "$basePath\Docker" -Recurse -Filter "*.vhdx" -ErrorAction SilentlyContinue +$vhdxFilesAfter += Get-ChildItem -Path "$basePath\Packages" -Recurse -Filter "ext4.vhdx" -ErrorAction SilentlyContinue +$vhdxFilesAfter = $vhdxFilesAfter | Sort-Object FullName -Unique +$totalAfter = ($vhdxFilesAfter | Measure-Object Length -Sum).Sum + +$savedTotal = [math]::Round(($totalBefore - $totalAfter) / 1GB, 2) + +Write-Host "════════════════════════════════════════════════════════════" -ForegroundColor Cyan +Write-Host (" Gesamt: {0} GB → {1} GB (gespart: {2} GB)" -f ` + [math]::Round($totalBefore / 1GB, 2), + [math]::Round($totalAfter / 1GB, 2), + $savedTotal) -ForegroundColor Cyan +Write-Host "════════════════════════════════════════════════════════════" -ForegroundColor Cyan +Write-Host "" +Write-Host "Fertig. Docker Desktop / WSL2 starten ja von alleine wieder beim naechsten Aufruf." -ForegroundColor Green