[APORTE] [PowerShell] Desactivar directivas de caché de escritura en todos los discos conectados.
(1/1)
Eleкtro:
El siguiente script, desarrollado en PowerShell, sirve para desactivar las directivas de caché de escritura en todos los discos físicos actualmente conectados, para evitar que cada disco tenga una configuración distinta y asegurarse de que el comportamiento de escritura en disco sea coherente y seguro en todo el sistema, evitando riesgo de pérdida de datos o fallo del disco por un corte de luz. Y sí, uso la palabra evitar, y lo hago en modo afirmativo, ya que en más de 15 años con la caché desactivada y muchos cortes de luz (y un apagón en España) no he sufrido pérdida de datos ni fallos en ninguno de mis discos ni una sola vez. Antes de adquirir el hábito de desactivar la caché, sí tuve muchos problemas con cada corte de luz, pero después de adquirir el hábito, ni uno solo. Por ese motivo recomiendo encarecidamente mantener siempre desactivada la caché de escritura en todos los discos. El disco irá más lento, pero eso que pierdes lo ganas multiplicado en seguridad.
La primera casilla de arriba viene activada por defecto en Windows cuando se detecta un nuevo disco conectado.
El script se ha desarrollado mediante vibe coding con inteligencia artificial, y un poco de edición manual en el código resultante. Lo hice para un amigo y lo comparto tal cual.
Código
#Requires -RunAsAdministrator
Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"
# Disable both write-cache options on ALL connected disk drives
# Option 1: Turn off write caching on the device > UserWriteCacheSetting = 0
# Option 2: Turn off Windows write-cache flushing > CacheIsPowerProtected = 0
[int] $successCount = 0
[int] $failCount = 0
Write-Host ""
Write-Host "============================================================" -ForegroundColor Cyan
Write-Host " Disable Write-Cache Options - All Physical Disks" -ForegroundColor Cyan
Write-Host "============================================================" -ForegroundColor Cyan
Write-Host ""
[System.Object[]] $diskDevices = @(
Get-PnpDevice -Class DiskDrive -Status OK -ErrorAction SilentlyContinue
)
if ($diskDevices.Count -eq 0) {
Write-Warning "No disk drives found with status OK."
Write-Host "Press any key to exit..."
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
exit 1
}
[System.Collections.Hashtable] $driveLetterMap = @{}
[System.Collections.Hashtable] $diskSizeMap = @{}
[System.Collections.Hashtable] $diskLabelMap = @{}
function Format-DiskSize {
param([uint64] $sizeBytes)
if ($sizeBytes -ge 1TB) { return "$([math]::Round($sizeBytes / 1TB, 2)) TB" }
elseif ($sizeBytes -ge 1GB) { return "$([math]::Round($sizeBytes / 1GB, 2)) GB" }
else { return "$([math]::Round($sizeBytes / 1MB, 2)) MB" }
}
Get-CimInstance -ClassName Win32_LogicalDisk -ErrorAction SilentlyContinue | ForEach-Object {
[string] $letter = $_.DeviceID
[object] $diskDrive = $_ |
Get-CimAssociatedInstance -ResultClassName Win32_DiskPartition -ErrorAction SilentlyContinue |
Get-CimAssociatedInstance -ResultClassName Win32_DiskDrive -ErrorAction SilentlyContinue |
Select-Object -First 1
if ($null -ne $diskDrive) {
[string] $pnpId = $diskDrive.PNPDeviceID.ToUpper()
if (-not $driveLetterMap.ContainsKey($pnpId)) {
$driveLetterMap[$pnpId] = $letter
}
if (-not $diskSizeMap.ContainsKey($pnpId)) {
$diskSizeMap[$pnpId] = [uint64]$diskDrive.Size
}
if (-not $diskLabelMap.ContainsKey($pnpId)) {
$diskLabelMap[$pnpId] = [string]$_.VolumeName
}
}
}
# Sort disk devices by their first drive letter; disks without letter go last
[System.Object[]] $sortedDevices = @(
$diskDevices | Sort-Object -Property {
[string] $key = $_.InstanceId.ToUpper()
if ($driveLetterMap.ContainsKey($key)) { $driveLetterMap[$key] } else { 'ZZ:' }
}
)
Write-Host "Found $($sortedDevices.Count) disk(s). Processing...`n" -ForegroundColor Yellow
foreach ($device in $sortedDevices) {
[string] $friendlyName = $device.FriendlyName
[string] $instanceId = $device.InstanceId
[string] $driveLetter = $driveLetterMap[$instanceId.ToUpper()]
[string] $diskSize = Format-DiskSize -sizeBytes $diskSizeMap[$instanceId.ToUpper()]
[string] $diskLabel = $diskLabelMap[$instanceId.ToUpper()]
[string] $regPath = "HKLM:\SYSTEM\CurrentControlSet\Enum\$instanceId\Device Parameters\Disk"
Write-Host "-----------------------------------------------------" -ForegroundColor DarkGray
Write-Host " Disk : [$driveLetter] $diskLabel - $friendlyName ($diskSize)" -ForegroundColor White
Write-Host " ID : $instanceId" -ForegroundColor DarkGray
if (-not (Test-Path -Path $regPath)) {
Write-Warning " Registry path not found - skipping: $regPath"
$failCount++
continue
}
# Option 1: Disable write caching
# UserWriteCacheSetting:
# 0 = System default | 1 = Force ENABLE | 2 = Force DISABLE
try {
Set-ItemProperty -Path $regPath `
-Name "UserWriteCacheSetting" `
-Value 0 `
-Type DWord `
-Force
Write-Host " [OK] Enable write caching DISABLED (UserWriteCacheSetting = 0)" -ForegroundColor Green
} catch {
Write-Warning " [FAIL] UserWriteCacheSetting - $_"
$failCount++
}
# Option 2: Re-enable buffer flushing (uncheck "turn off flushing")
# CacheIsPowerProtected:
# 0 = Flushing ENABLED (checkbox unchecked - safe mode)
# 1 = Flushing DISABLED (checkbox checked - risky, power-loss danger)
try {
Set-ItemProperty -Path $regPath `
-Name "CacheIsPowerProtected" `
-Value 0 `
-Type DWord `
-Force
Write-Host " [OK] Turn off write-cache buffer flushing DISABLED (CacheIsPowerProtected = 0)" -ForegroundColor Green
$successCount++
} catch {
Write-Warning " [FAIL] CacheIsPowerProtected - $_"
$failCount++
}
}
# Summary
Write-Host ""
Write-Host "============================================================" -ForegroundColor Cyan
Write-Host " Summary" -ForegroundColor Cyan
Write-Host "============================================================" -ForegroundColor Cyan
Write-Host " Disks processed successfully : $successCount" -ForegroundColor Green
if ($failCount -gt 0) {
Write-Host " Disks with errors : $failCount" -ForegroundColor Red
}
Write-Host ""
Write-Host " NOTE: A system RESTART is required for changes" -ForegroundColor Yellow
Write-Host " to take effect on all devices." -ForegroundColor Yellow
Write-Host ""
Write-Host "Press any key to exit..."
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
Danielㅤ:
Hola compañero Elektro, interesante lo que has comentado y recomendado, y el script está bueno para realizar más fácil y rápida la configuración.
Importante: Luego de hacer la modificación que indica el compañero, hay que reiniciar la PC.
Navegación