Skip to content

Windows System Integrity: SFC, DISM, and Automated Health Checks

Goal: Verify and repair Windows system file integrity using built-in tools (SFC, DISM, chkdsk, bootrec) Level: Intermediate → Advanced Language: English


Table of Contents: How It Works | SFC | DISM | Correct Repair Sequence | Boot Repair | Windows Update Integrity | Driver Integrity | Registry Integrity | Automated Script | Quick Reference


A practical guide to verifying and repairing Windows system file integrity using built-in tools. When system files become corrupted — due to disk errors, power loss, failed updates, or malware — these tools detect and restore them from known-good sources.

How Windows System Integrity Works

Windows maintains integrity through multiple layers:

Layer 1: Component Store (WinSxS)
  └── The master copy of all system files, managed by CBS (Component Based Servicing)
  └── Location: C:\Windows\WinSxS
  └── Repaired by: DISM

Layer 2: System Files (System32, etc.)
  └── Active copies deployed from the Component Store
  └── Protected by: Windows Resource Protection (WRP)
  └── Repaired by: SFC

Layer 3: Boot Files (BCD, bootloader)
  └── Boot configuration and loader
  └── Repaired by: bootrec, bcdboot

Layer 4: Filesystem Structure
  └── NTFS metadata, directory entries, MFT
  └── Repaired by: chkdsk

Correct repair order

Always work bottom-up: fix the filesystem first (chkdsk), then the component store (DISM), then the system files (SFC), then boot files if needed (bootrec).


SFC — System File Checker

SFC scans all protected system files and replaces corrupted or modified files with the correct version from the Component Store (WinSxS).

Basic Usage

# Run from an elevated (Administrator) PowerShell or Command Prompt

# Full system scan and automatic repair
sfc /scannow

# Verify only (no repair)
sfc /verifyonly

# Scan a specific file
sfc /scanfile=C:\Windows\System32\kernel32.dll

# Verify a specific file
sfc /verifyfile=C:\Windows\System32\kernel32.dll

Understanding SFC Output

Message Meaning Action
Windows Resource Protection did not find any integrity violations. All system files are intact No action needed
Windows Resource Protection found corrupt files and successfully repaired them. Corruption found and fixed Check the log for details
Windows Resource Protection found corrupt files but was unable to fix some of them. Corruption found, repair failed Run DISM first, then SFC again
Windows Resource Protection could not perform the requested operation. SFC itself cannot run Boot to Safe Mode or Recovery

Reading the SFC Log

SFC writes detailed results to a log file:

# View the SFC log (CBS.log filtered for SFC entries)
findstr /c:"[SR]" %windir%\Logs\CBS\CBS.log > "%userprofile%\Desktop\sfclog.txt"

# Or in PowerShell
Select-String -Path "$env:windir\Logs\CBS\CBS.log" -Pattern "\[SR\]" |
    Select-Object -Last 100 |
    ForEach-Object { $_.Line }

Log entries to look for:

# Healthy file
[SR] Verifying 100 (0x0064) [l:24]"kernel32.dll" ... hash matches

# Corrupted and repaired
[SR] Cannot repair member file [l:24]"example.dll" ... hash mismatch
[SR] Repairing file [l:24]"example.dll" from store

# Cannot repair (Component Store also damaged)
[SR] Cannot repair member file [l:24]"example.dll"
[SR] This component was referenced by [l:...]

Offline SFC (from Recovery Environment)

When to use offline SFC

When Windows cannot boot, run SFC from the Recovery Environment or a Windows installation USB. The drive letter may differ from the normal boot environment.

# Boot from Windows installation media
# Select "Repair your computer" > Command Prompt

# Find the Windows drive letter (may not be C: in recovery)
wmic logicaldisk get caption,volumename

# Run SFC targeting the offline Windows installation
sfc /scannow /offbootdir=D:\ /offwindir=D:\Windows

DISM — Deployment Image Servicing and Management

DISM repairs the Component Store itself — the source that SFC uses for repairs. If SFC reports it cannot fix files, DISM is the next step.

Health Check (Read-Only)

# Quick check — is the component store flagged as needing repair?
DISM /Online /Cleanup-Image /CheckHealth

# Deeper scan — actually verify component store integrity
DISM /Online /Cleanup-Image /ScanHealth
Command Speed What It Does
/CheckHealth Instant Checks if a corruption flag is set (from a previous scan)
/ScanHealth Minutes Actually scans the component store for corruption

Repair

# Repair the component store using Windows Update as the source
DISM /Online /Cleanup-Image /RestoreHealth

# Repair using a local Windows image (ISO mounted or install media)
DISM /Online /Cleanup-Image /RestoreHealth /Source:E:\Sources\install.wim

# Repair using a specific image index from the WIM
DISM /Online /Cleanup-Image /RestoreHealth /Source:wim:E:\Sources\install.wim:1

# Prevent DISM from using Windows Update (offline repair only)
DISM /Online /Cleanup-Image /RestoreHealth /Source:E:\Sources\install.wim /LimitAccess

DISM Output

Message Meaning
The component store is repairable. Corruption found, can be fixed
No component store corruption detected. Component store is healthy
The restore operation completed successfully. Repairs applied successfully
Error: 0x800f081f Source files not found — provide a Windows image
Error: 0x800f0906 Cannot download from Windows Update — use local source

Additional DISM Operations

# Clean up superseded components (free disk space)
DISM /Online /Cleanup-Image /StartComponentCleanup

# Aggressive cleanup (removes ALL superseded versions — see warning below)
DISM /Online /Cleanup-Image /StartComponentCleanup /ResetBase

# Check installed packages
DISM /Online /Get-Packages

# Check specific feature state
DISM /Online /Get-Features | findstr /i "NetFx"

ResetBase is irreversible

/StartComponentCleanup /ResetBase removes all superseded component versions. After running it, you cannot uninstall any previously installed updates. Only use this when you are certain you do not need to roll back.

DISM Log

DISM logs to a separate file:

# View DISM log
notepad "$env:windir\Logs\DISM\dism.log"

# Or search for errors
Select-String -Path "$env:windir\Logs\DISM\dism.log" -Pattern "Error|Warning|Failed" |
    Select-Object -Last 50 |
    ForEach-Object { $_.Line }

The Correct Repair Sequence

When dealing with system file corruption, follow this order:

Step 1: chkdsk
  └── Fix filesystem structure first
  └── Without a healthy filesystem, file-level repairs are unreliable

Step 2: DISM /RestoreHealth
  └── Repair the Component Store
  └── This restores the "source of truth" that SFC needs

Step 3: sfc /scannow
  └── Repair system files from the (now healthy) Component Store

Step 4: Reboot and verify
  └── Some repairs require a restart to take effect
  └── Run sfc /scannow again after reboot to confirm

Step 5 (if needed): bootrec
  └── Repair boot configuration if the system won't start

Full Repair Sequence Commands

# Step 1: Check filesystem (schedule for next boot if on system drive)
chkdsk C: /f /r

# Step 2: Repair Component Store
DISM /Online /Cleanup-Image /RestoreHealth

# Step 3: Repair system files
sfc /scannow

# Step 4: Reboot
Restart-Computer

# Step 5 (after reboot): Verify
sfc /verifyonly

Boot Repair Tools

When Windows cannot boot at all, use these from the Recovery Environment:

bootrec

# Rebuild the Boot Configuration Data
bootrec /rebuildbcd

# Fix the Master Boot Record
bootrec /fixmbr

# Fix the boot sector
bootrec /fixboot

# Scan for Windows installations
bootrec /scanos

bcdboot

# Rebuild BCD store from a Windows installation
bcdboot C:\Windows /s S: /f UEFI

# For BIOS/MBR systems
bcdboot C:\Windows /s S: /f BIOS

Windows Update Integrity

Failed Windows updates can leave the system in an inconsistent state.

Check Windows Update Health

# Check for pending updates and their state
Get-WindowsUpdate -ErrorAction SilentlyContinue

# View Windows Update log (Windows 10/11)
Get-WindowsUpdateLog

# Check update history
Get-HotFix | Sort-Object InstalledOn -Descending | Select-Object -First 20

# Check for failed updates in Event Log
Get-WinEvent -FilterHashtable @{
    LogName = 'System'
    ProviderName = 'Microsoft-Windows-WindowsUpdateClient'
} -MaxEvents 20 -ErrorAction SilentlyContinue |
ForEach-Object {
    Write-Host "[$($_.TimeCreated)] ID:$($_.Id) $($_.Message.Substring(0, [Math]::Min($_.Message.Length, 150)))"
}

Reset Windows Update Components

Use as a last resort

This procedure stops core update services and renames their cache folders. Only use it when Windows Update is completely broken and normal troubleshooting has failed.

# Stop update services
Stop-Service -Name wuauserv, cryptSvc, bits, msiserver -Force

# Rename cache folders (backup)
Rename-Item "$env:windir\SoftwareDistribution" "SoftwareDistribution.old"
Rename-Item "$env:windir\System32\catroot2" "catroot2.old"

# Restart services
Start-Service -Name wuauserv, cryptSvc, bits, msiserver

# Trigger a fresh update scan
Start-Process "USOClient.exe" "StartScan"

Driver Integrity

Corrupted drivers can cause BSODs and hardware malfunctions.

Check Driver Signing

# List all drivers and their signing status
driverquery /v | findstr /i "not signed"

# Or use PowerShell for more detail
Get-WmiObject Win32_PnPSignedDriver |
    Where-Object { $_.IsSigned -eq $false } |
    Select-Object DeviceName, DriverVersion, Manufacturer |
    Format-Table -AutoSize

Verify System Driver Integrity

# sigverif — GUI tool for driver signature verification
sigverif

# Or use the System Information tool
msinfo32
# Navigate to: Software Environment > Signed Drivers

Registry Integrity

Registry is a critical system database

Corruption in the Windows Registry can prevent boot or cause erratic behavior. Always create a backup before making manual registry changes.

Built-in Registry Backup

Disabled by default since Windows 10 1803

Automatic registry backup to RegBack is disabled by default in Windows 10 version 1803 and later. You must re-enable it via Task Scheduler (see command below).

# Windows automatically backs up the registry to:
# C:\Windows\System32\config\RegBack\

# Check if RegBack contains recent files
Get-ChildItem "$env:windir\System32\config\RegBack" | 
    Select-Object Name, Length, LastWriteTime |
    Format-Table -AutoSize

# Re-enable automatic registry backup via Task Scheduler
# Task: \Microsoft\Windows\Registry\RegIdleBackup
schtasks /Change /TN "Microsoft\Windows\Registry\RegIdleBackup" /Enable

Manual Registry Backup

# Export entire registry (large file)
reg export HKLM "$env:userprofile\Desktop\HKLM_backup.reg"
reg export HKCU "$env:userprofile\Desktop\HKCU_backup.reg"

# Export specific key
reg export "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion" "$env:userprofile\Desktop\CurrentVersion_backup.reg"

The Complete System Integrity Script

system_integrity_check.ps1 - Click to expand
# Windows System Integrity Check
# Run from an elevated (Administrator) PowerShell session
# Usage: .\system_integrity_check.ps1 | Tee-Object -FilePath integrity_report.txt

param(
    [switch]$Repair,
    [switch]$Full
)

$ErrorActionPreference = "Continue"

Write-Host "============================================"
Write-Host "  SYSTEM INTEGRITY CHECK"
Write-Host "  $(Get-Date)"
if ($Repair) { Write-Host "  MODE: SCAN + REPAIR" -ForegroundColor Yellow }
else { Write-Host "  MODE: SCAN ONLY (use -Repair to fix)" }
Write-Host "============================================"

# 1. OS Information
Write-Host "`n=== 1. SYSTEM INFORMATION ==="
$os = Get-WmiObject Win32_OperatingSystem
Write-Host "  OS:       $($os.Caption) $($os.Version)"
Write-Host "  Build:    $($os.BuildNumber)"
Write-Host "  Install:  $($os.ConvertToDateTime($os.InstallDate))"
Write-Host "  Uptime:   $(((Get-Date) - $os.ConvertToDateTime($os.LastBootUpTime)).ToString('d\.hh\:mm\:ss'))"

# 2. Disk Health (prerequisite for integrity checks)
Write-Host "`n=== 2. VOLUME HEALTH ==="
Get-Volume | Where-Object { $_.DriveLetter -and $_.FileSystem } |
    Sort-Object DriveLetter | ForEach-Object {
    $letter = $_.DriveLetter
    $health = $_.HealthStatus
    $fs = $_.FileSystem
    $sizeGB = [math]::Round($_.Size / 1GB, 1)
    $freeGB = [math]::Round($_.SizeRemaining / 1GB, 1)
    $status = if ($health -ne "Healthy") { " !! UNHEALTHY !!" } else { "" }
    Write-Host "  ${letter}: $fs - Health: ${health} - ${freeGB}/${sizeGB}GB free${status}"
}

# 3. DISM Component Store Health
Write-Host "`n=== 3. COMPONENT STORE (DISM) ==="
if ($Full) {
    Write-Host "  Running DISM ScanHealth (deep scan, may take several minutes)..."
    if ($Repair) {
        $dismResult = & DISM /Online /Cleanup-Image /RestoreHealth 2>&1
    } else {
        $dismResult = & DISM /Online /Cleanup-Image /ScanHealth 2>&1
    }
} else {
    Write-Host "  Running DISM CheckHealth (quick check)..."
    $dismResult = & DISM /Online /Cleanup-Image /CheckHealth 2>&1
}
$dismOutput = $dismResult | Out-String
if ($dismOutput -match "No component store corruption") {
    Write-Host "  Result: HEALTHY" -ForegroundColor Green
} elseif ($dismOutput -match "repairable") {
    Write-Host "  Result: CORRUPTION DETECTED (repairable)" -ForegroundColor Red
    if (-not $Repair) {
        Write-Host "  Run with -Repair flag to fix."
    }
} elseif ($dismOutput -match "restore operation completed successfully") {
    Write-Host "  Result: REPAIRED SUCCESSFULLY" -ForegroundColor Yellow
} else {
    Write-Host "  Result:"
    $dismResult | ForEach-Object { Write-Host "    $_" }
}

# 4. SFC System File Check
Write-Host "`n=== 4. SYSTEM FILE CHECKER (SFC) ==="
if ($Repair) {
    Write-Host "  Running sfc /scannow (scan + repair, may take several minutes)..."
    $sfcResult = & sfc /scannow 2>&1
} else {
    Write-Host "  Running sfc /verifyonly (scan only, may take several minutes)..."
    $sfcResult = & sfc /verifyonly 2>&1
}
$sfcOutput = $sfcResult | Out-String
if ($sfcOutput -match "did not find any integrity violations") {
    Write-Host "  Result: ALL FILES INTACT" -ForegroundColor Green
} elseif ($sfcOutput -match "successfully repaired") {
    Write-Host "  Result: CORRUPTION FOUND AND REPAIRED" -ForegroundColor Yellow
} elseif ($sfcOutput -match "unable to fix") {
    Write-Host "  Result: CORRUPTION FOUND - REPAIR FAILED" -ForegroundColor Red
    Write-Host "  Run DISM /Online /Cleanup-Image /RestoreHealth first, then retry."
} else {
    Write-Host "  Result:"
    $sfcResult | ForEach-Object { Write-Host "    $_" }
}

# 5. Recent SFC Log Entries
Write-Host "`n=== 5. RECENT SFC LOG ==="
$cbsLog = "$env:windir\Logs\CBS\CBS.log"
if (Test-Path $cbsLog) {
    $sfcEntries = Select-String -Path $cbsLog -Pattern "\[SR\]" |
        Select-Object -Last 20
    if ($sfcEntries) {
        $corrupted = $sfcEntries | Where-Object { $_.Line -match "Cannot repair|hash mismatch|corrupt" }
        $repaired = $sfcEntries | Where-Object { $_.Line -match "Repairing|repaired|Successfully" }
        Write-Host "  Last 20 SFC log entries:"
        Write-Host "    Corruption entries: $(($corrupted | Measure-Object).Count)"
        Write-Host "    Repair entries:     $(($repaired | Measure-Object).Count)"
        if ($corrupted) {
            Write-Host "  Corrupted files found:" -ForegroundColor Red
            $corrupted | ForEach-Object {
                $line = $_.Line
                if ($line.Length -gt 150) { $line = $line.Substring(0, 150) + "..." }
                Write-Host "    $line"
            }
        }
    } else {
        Write-Host "  No SFC entries in CBS.log."
    }
} else {
    Write-Host "  CBS.log not found."
}

# 6. DISM Log Errors
Write-Host "`n=== 6. RECENT DISM ERRORS ==="
$dismLog = "$env:windir\Logs\DISM\dism.log"
if (Test-Path $dismLog) {
    $dismErrors = Select-String -Path $dismLog -Pattern "Error|HRESULT" |
        Select-Object -Last 10
    if ($dismErrors) {
        Write-Host "  Last 10 DISM error entries:"
        $dismErrors | ForEach-Object {
            $line = $_.Line.Trim()
            if ($line.Length -gt 150) { $line = $line.Substring(0, 150) + "..." }
            Write-Host "    $line"
        }
    } else {
        Write-Host "  No errors in DISM log." -ForegroundColor Green
    }
} else {
    Write-Host "  DISM log not found."
}

# 7. Windows Update Status
Write-Host "`n=== 7. WINDOWS UPDATE STATUS ==="
$lastUpdates = Get-HotFix -ErrorAction SilentlyContinue |
    Sort-Object InstalledOn -Descending -ErrorAction SilentlyContinue |
    Select-Object -First 5
if ($lastUpdates) {
    Write-Host "  Last 5 installed updates:"
    foreach ($upd in $lastUpdates) {
        Write-Host "    $($upd.HotFixID) - $($upd.InstalledOn) - $($upd.Description)"
    }
}

# Failed update events
$updateErrors = Get-WinEvent -FilterHashtable @{
    LogName = 'System'
    ProviderName = 'Microsoft-Windows-WindowsUpdateClient'
    Level = 2
} -MaxEvents 5 -ErrorAction SilentlyContinue

if ($updateErrors) {
    Write-Host "`n  Recent Windows Update errors:" -ForegroundColor Red
    foreach ($ev in $updateErrors) {
        $msg = $ev.Message
        if ($msg.Length -gt 150) { $msg = $msg.Substring(0, 150) + "..." }
        Write-Host "    [$($ev.TimeCreated)] $msg"
    }
} else {
    Write-Host "  No recent Windows Update errors." -ForegroundColor Green
}

# 8. Unsigned Drivers
Write-Host "`n=== 8. DRIVER INTEGRITY ==="
$unsignedDrivers = Get-WmiObject Win32_PnPSignedDriver -ErrorAction SilentlyContinue |
    Where-Object { $_.IsSigned -eq $false -and $_.DeviceName }

if ($unsignedDrivers) {
    Write-Host "  Unsigned drivers found:" -ForegroundColor Yellow
    foreach ($drv in $unsignedDrivers) {
        Write-Host "    $($drv.DeviceName) - $($drv.Manufacturer) - v$($drv.DriverVersion)"
    }
} else {
    Write-Host "  All loaded drivers are signed." -ForegroundColor Green
}

# 9. Secure Boot Status
Write-Host "`n=== 9. SECURE BOOT ==="
try {
    $secureBoot = Confirm-SecureBootUEFI -ErrorAction Stop
    if ($secureBoot) {
        Write-Host "  Secure Boot: ENABLED" -ForegroundColor Green
    } else {
        Write-Host "  Secure Boot: DISABLED" -ForegroundColor Yellow
    }
} catch {
    Write-Host "  Secure Boot: NOT SUPPORTED or BIOS mode"
}

# 10. Pending Reboot Check
Write-Host "`n=== 10. PENDING OPERATIONS ==="
$pendingReboot = $false

# Check Component Based Servicing
$cbsKey = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootPending"
if (Test-Path $cbsKey) {
    Write-Host "  Component Based Servicing: REBOOT PENDING" -ForegroundColor Yellow
    $pendingReboot = $true
}

# Check Windows Update
$wuKey = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired"
if (Test-Path $wuKey) {
    Write-Host "  Windows Update: REBOOT REQUIRED" -ForegroundColor Yellow
    $pendingReboot = $true
}

# Check pending file rename operations
$pfro = Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager" -Name PendingFileRenameOperations -ErrorAction SilentlyContinue
if ($pfro.PendingFileRenameOperations) {
    $count = ($pfro.PendingFileRenameOperations | Where-Object { $_ }).Count
    Write-Host "  Pending file renames: $count operations" -ForegroundColor Yellow
    $pendingReboot = $true
}

if (-not $pendingReboot) {
    Write-Host "  No pending reboots or operations." -ForegroundColor Green
}

# 11. Registry Backup Status
Write-Host "`n=== 11. REGISTRY BACKUP ==="
$regBack = "$env:windir\System32\config\RegBack"
if (Test-Path $regBack) {
    $regFiles = Get-ChildItem $regBack -ErrorAction SilentlyContinue
    $nonEmpty = $regFiles | Where-Object { $_.Length -gt 0 }
    if ($nonEmpty) {
        Write-Host "  RegBack files:"
        foreach ($rf in $nonEmpty) {
            $ageD = [math]::Round(((Get-Date) - $rf.LastWriteTime).TotalDays, 1)
            $sizeKB = [math]::Round($rf.Length / 1KB, 0)
            $fresh = if ($ageD -gt 30) { " [STALE]" } else { "" }
            Write-Host "    $($rf.Name) - ${sizeKB}KB - ${ageD} days old${fresh}"
        }
    } else {
        Write-Host "  RegBack exists but files are 0 bytes (disabled since Win10 1803)." -ForegroundColor Yellow
        Write-Host "  To enable: schtasks /Change /TN '\Microsoft\Windows\Registry\RegIdleBackup' /Enable"
    }
} else {
    Write-Host "  RegBack directory not found." -ForegroundColor Yellow
}

# 12. Summary
Write-Host "`n=== SUMMARY ==="
Write-Host ""
Write-Host "  Checks completed. Review any RED or YELLOW items above."
if (-not $Repair) {
    Write-Host ""
    Write-Host "  To repair issues, run:"
    Write-Host "    .\system_integrity_check.ps1 -Repair       (quick DISM + SFC)"
    Write-Host "    .\system_integrity_check.ps1 -Repair -Full (deep DISM scan + SFC)"
}
if ($pendingReboot) {
    Write-Host ""
    Write-Host "  !! A reboot is pending. Restart the system before running repairs. !!" -ForegroundColor Yellow
}

Write-Host "`n============================================"
Write-Host "  DONE"
Write-Host "============================================"

Quick Reference

Repair Commands (Correct Order)

Step Command Duration Requires Reboot
1 chkdsk C: /f /r 30min - 4hrs Yes (scheduled)
2 DISM /Online /Cleanup-Image /RestoreHealth 5-30 min No
3 sfc /scannow 5-20 min Sometimes
4 sfc /verifyonly (confirm) 5-20 min No

Diagnostic Commands (Read-Only)

Task Command
Quick component store check DISM /Online /Cleanup-Image /CheckHealth
Deep component store scan DISM /Online /Cleanup-Image /ScanHealth
Verify system files (no repair) sfc /verifyonly
View SFC results findstr /c:"[SR]" %windir%\Logs\CBS\CBS.log
View DISM log notepad %windir%\Logs\DISM\dism.log
Check pending reboot Get-ItemProperty "HKLM:\SOFTWARE\...\RebootPending"
Recent updates Get-HotFix \| Sort-Object InstalledOn -Descending
Unsigned drivers driverquery /v \| findstr "not signed"
Secure Boot status Confirm-SecureBootUEFI

Recovery Environment Commands

Task Command
Offline SFC sfc /scannow /offbootdir=D:\ /offwindir=D:\Windows
Rebuild BCD bootrec /rebuildbcd
Fix MBR bootrec /fixmbr
Fix boot sector bootrec /fixboot
Rebuild bootloader (UEFI) bcdboot C:\Windows /s S: /f UEFI