Public/Invoke-TechCareRepair.ps1
|
function Invoke-TechCareRepair { <# .SYNOPSIS Repara la imagen del sistema y los archivos protegidos de Windows. .DESCRIPTION Ejecuta DISM /RestoreHealth, despues sfc /scannow y por ultimo chkdsk en modo escaneo. chkdsk se lanza con /scan, que es solo lectura y en linea: no repara, no desmonta el volumen y no programa un reinicio. Requiere administrador. Sin elevacion devuelve estado Gris y no intenta nada, porque DISM sin privilegios falla a medias. .PARAMETER SkipChkdsk Omite el escaneo de chkdsk, que es la fase mas larga en discos grandes. .EXAMPLE Invoke-TechCareRepair -WhatIf Muestra las tres fases que se ejecutarian sin tocar nada. .EXAMPLE Invoke-TechCareRepair -Confirm:$false Ejecuta las tres fases sin pedir confirmacion por cada una. .EXAMPLE Invoke-TechCareRepair -SkipChkdsk -Confirm:$false Repara imagen y archivos protegidos, sin escanear el volumen. .OUTPUTS PSCustomObject .LINK https://github.com/earbona23/TechCare #> [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'Medium')] [OutputType([pscustomobject])] param( [switch]$SkipChkdsk ) if (-not (Test-TechCarePlatform)) { throw $script:PlatformMessage } $findings = New-Object -TypeName System.Collections.ArrayList $actions = New-Object -TypeName System.Collections.ArrayList $recs = New-Object -TypeName System.Collections.ArrayList $status = 'Green' $mod = 'Repair' if (-not (Test-TechCareAdmin)) { [void]$findings.Add('Sin privilegios de administrador: Repair omitido.') [void]$recs.Add('Relanzar la consola como administrador para ejecutar Repair.') Write-TechCareLog -ModuleName $mod -Level Warning -Message 'Repair omitido por falta de privilegios.' return Add-TechCareResult -Module $mod -Status 'Gray' -Findings $findings.ToArray() -Recommendations $recs.ToArray() } $dism = Join-Path -Path $env:SystemRoot -ChildPath 'System32\DISM.exe' $sfc = Join-Path -Path $env:SystemRoot -ChildPath 'System32\sfc.exe' $chkdsk = Join-Path -Path $env:SystemRoot -ChildPath 'System32\chkdsk.exe' if ($PSCmdlet.ShouldProcess('Imagen de Windows', 'DISM /Online /Cleanup-Image /RestoreHealth')) { Write-Progress -Activity 'TechCare' -Status 'DISM RestoreHealth' -PercentComplete 20 Write-TechCareLog -ModuleName $mod -Message 'Ejecutando DISM RestoreHealth (puede tardar varios minutos, no lo interrumpas).' $r = Invoke-TechCareProcess -FilePath $dism -ArgumentList @('/Online', '/Cleanup-Image', '/RestoreHealth') if ($r.ExitCode -eq 0) { [void]$actions.Add('DISM RestoreHealth completado (codigo 0).') } elseif ($r.ExitCode -eq 3010) { # 3010 es ERROR_SUCCESS_REBOOT_REQUIRED: la reparacion funciono. [void]$actions.Add('DISM RestoreHealth completado; requiere reinicio (3010).') [void]$recs.Add('Reiniciar para consolidar la reparacion de imagen.') } else { $status = 'Yellow' [void]$findings.Add(('DISM devolvio codigo {0}.' -f $r.ExitCode)) [void]$recs.Add('Revisar %WinDir%\Logs\CBS\CBS.log si DISM persiste en fallo.') Write-TechCareLog -ModuleName $mod -Level Warning -Message 'DISM con codigo distinto de 0.' -ErrorText $r.Output } } if ($PSCmdlet.ShouldProcess('Archivos protegidos del sistema', 'sfc /scannow')) { Write-Progress -Activity 'TechCare' -Status 'sfc /scannow' -PercentComplete 55 Write-TechCareLog -ModuleName $mod -Message 'Ejecutando sfc /scannow.' $r = Invoke-TechCareProcess -FilePath $sfc -ArgumentList @('/scannow') # sfc esta localizado y no distingue sus casos por codigo de salida, asi # que hay que leer el texto. Se cubren espanol e ingles; cualquier otro # idioma cae en la rama no concluyente y queda registrado en bruto. if ($r.Output -match 'no ha encontrado|did not find any integrity violations') { [void]$actions.Add('sfc: sin infracciones de integridad.') } elseif ($r.Output -match 'reparado correctamente|successfully repaired') { $status = 'Yellow' [void]$actions.Add('sfc: archivos danados reparados.') [void]$recs.Add('Hubo dano en archivos del sistema: vigilar el equipo los proximos dias.') } elseif ($r.Output -match 'no pudo reparar|unable to fix') { $status = 'Yellow' [void]$findings.Add('sfc detecto dano que no pudo reparar.') [void]$recs.Add('Revisar CBS.log y valorar una reparacion in-place de Windows.') } else { [void]$actions.Add('sfc ejecutado; salida no concluyente, registrada en el log.') } Write-TechCareLog -ModuleName $mod -Level Detail -Message 'Salida de sfc registrada.' -ErrorText $r.Output } if (-not $SkipChkdsk) { $target = $env:SystemDrive if ($PSCmdlet.ShouldProcess(('Volumen {0}' -f $target), 'chkdsk /scan (solo lectura, sin reinicio)')) { Write-Progress -Activity 'TechCare' -Status 'chkdsk /scan' -PercentComplete 80 Write-TechCareLog -ModuleName $mod -Message ('Escaneo chkdsk en {0} (sin reparacion).' -f $target) $r = Invoke-TechCareProcess -FilePath $chkdsk -ArgumentList @($target, '/scan') if ($r.ExitCode -eq 0) { [void]$actions.Add('chkdsk /scan sin problemas detectados.') } else { $status = 'Yellow' [void]$findings.Add(('chkdsk /scan devolvio codigo {0}.' -f $r.ExitCode)) [void]$recs.Add('Ejecutar chkdsk /spotfix en ventana de mantenimiento si procede. TechCare no lo hace por ti: /spotfix bloquea el volumen.') } Write-TechCareLog -ModuleName $mod -Level Detail -Message 'Salida de chkdsk registrada.' -ErrorText $r.Output } } else { [void]$findings.Add('chkdsk omitido por -SkipChkdsk.') } Write-Progress -Activity 'TechCare' -Status 'Reparacion completada' -Completed return Add-TechCareResult -Module $mod -Status $status -Findings $findings.ToArray() -Actions $actions.ToArray() -Recommendations $recs.ToArray() } |