mirror of
https://github.com/ChrisTitusTech/winutil.git
synced 2025-05-10 00:02:09 +00:00
Refactor Invoke-WPFSystemRepair to improve function naming, scalablility and fix on english os
This commit is contained in:
parent
642367509d
commit
ab97c776f9
@ -1,6 +1,5 @@
|
|||||||
function Invoke-WPFSystemRepair {
|
function Invoke-WPFSystemRepair {
|
||||||
<#
|
<#
|
||||||
|
|
||||||
.SYNOPSIS
|
.SYNOPSIS
|
||||||
Checks for system corruption using Chkdsk, SFC, and DISM
|
Checks for system corruption using Chkdsk, SFC, and DISM
|
||||||
|
|
||||||
@ -11,11 +10,7 @@ function Invoke-WPFSystemRepair {
|
|||||||
4. SFC Run 2 - Fixes system file corruption, this time with an almost guaranteed uncorrupted system image
|
4. SFC Run 2 - Fixes system file corruption, this time with an almost guaranteed uncorrupted system image
|
||||||
#>
|
#>
|
||||||
|
|
||||||
Write-Progress -Id 0 -Activity "Repairing Windows" -PercentComplete 0
|
function Invoke-Chkdsk {
|
||||||
# Wait for the first progress bar to show, otherwise the second one won't show
|
|
||||||
Start-Sleep -Milliseconds 200
|
|
||||||
|
|
||||||
function run_chkdsk {
|
|
||||||
<#
|
<#
|
||||||
.SYNOPSIS
|
.SYNOPSIS
|
||||||
Runs chkdsk on the system drive
|
Runs chkdsk on the system drive
|
||||||
@ -24,10 +19,11 @@ function Invoke-WPFSystemRepair {
|
|||||||
.PARAMETER verbose
|
.PARAMETER verbose
|
||||||
If specified, print output from chkdsk
|
If specified, print output from chkdsk
|
||||||
.NOTES
|
.NOTES
|
||||||
VerbosePreference is defined locally, so it only affects this function. This is done by wrapping the code inside a script block and calling it with & { ... }
|
VerbosePreference is set locally within a script block (& { ... }) to avoid affecting the global or parent scope.
|
||||||
#>
|
#>
|
||||||
param(
|
param(
|
||||||
[switch]$verbose
|
[switch]$verbose,
|
||||||
|
[int]$parentProgressId = 0
|
||||||
)
|
)
|
||||||
& {
|
& {
|
||||||
if ($verbose) {
|
if ($verbose) {
|
||||||
@ -36,8 +32,8 @@ function Invoke-WPFSystemRepair {
|
|||||||
else {
|
else {
|
||||||
$VerbosePreference = "SilentlyContinue"
|
$VerbosePreference = "SilentlyContinue"
|
||||||
}
|
}
|
||||||
|
|
||||||
Write-Progress -Id 1 -Activity "Scanning for corruption" -Status "Running chkdsk..." -PercentComplete 0
|
Write-Progress -Id 1 -ParentId $parentProgressId -Activity $childProgressBarActivity -Status "Running chkdsk..." -PercentComplete 0
|
||||||
$oldpercent = 0
|
$oldpercent = 0
|
||||||
# 2>&1 redirects stdout, allowing iteration over the output
|
# 2>&1 redirects stdout, allowing iteration over the output
|
||||||
chkdsk.exe /scan /perf 2>&1 | ForEach-Object {
|
chkdsk.exe /scan /perf 2>&1 | ForEach-Object {
|
||||||
@ -46,16 +42,16 @@ function Invoke-WPFSystemRepair {
|
|||||||
if ($_ -match "%.*?(\d+)%") {
|
if ($_ -match "%.*?(\d+)%") {
|
||||||
[int]$percent = $matches[1]
|
[int]$percent = $matches[1]
|
||||||
if ($percent -gt $oldpercent) {
|
if ($percent -gt $oldpercent) {
|
||||||
Write-Progress -Id 1 -ParentId 0 -Activity "Scanning for corruption" -Status "Running chkdsk... ($percent%)" -PercentComplete $percent
|
Write-Progress -Id 1 -Activity $childProgressBarActivity -Status "Running chkdsk... ($percent%)" -PercentComplete $percent
|
||||||
$oldpercent = $percent
|
$oldpercent = $percent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Write-Progress -Id 1 -Activity "Scanning for corruption" -Status "chkdsk Completed" -PercentComplete 100
|
Write-Progress -Id 1 -Activity $childProgressBarActivity -Status "chkdsk Completed" -PercentComplete 100 -Completed
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function run_sfc {
|
function Invoke-SFC {
|
||||||
<#
|
<#
|
||||||
.SYNOPSIS
|
.SYNOPSIS
|
||||||
Runs sfc on the system drive
|
Runs sfc on the system drive
|
||||||
@ -64,10 +60,13 @@ function Invoke-WPFSystemRepair {
|
|||||||
.PARAMETER verbose
|
.PARAMETER verbose
|
||||||
If specified, print output from sfc
|
If specified, print output from sfc
|
||||||
.NOTES
|
.NOTES
|
||||||
VerbosePreference and ErrorPreference is defined locally, so it only affects this function. This is done by wrapping the code inside a script block and calling it with & { ... }
|
VerbosePreference and ErrorActionPreference are set locally within a script block to isolate their effects. ErrorActionPreference suppresses false errors caused by sfc.exe output redirection.
|
||||||
|
A bug in SFC output buffering causes progress updates to appear in chunks when redirecting output
|
||||||
|
|
||||||
#>
|
#>
|
||||||
param(
|
param(
|
||||||
[switch]$verbose
|
[switch]$verbose,
|
||||||
|
[int]$parentProgressId = 0
|
||||||
)
|
)
|
||||||
|
|
||||||
& {
|
& {
|
||||||
@ -78,29 +77,27 @@ function Invoke-WPFSystemRepair {
|
|||||||
$VerbosePreference = "SilentlyContinue"
|
$VerbosePreference = "SilentlyContinue"
|
||||||
}
|
}
|
||||||
$ErrorActionPreference = "SilentlyContinue"
|
$ErrorActionPreference = "SilentlyContinue"
|
||||||
Write-Progress -Id 1 -ParentId 0 -Activity "Scanning for corruption" -Status "Running SFC..." -PercentComplete 0
|
Write-Progress -Id 1 -ParentId $parentProgressId -Activity $childProgressBarActivity -Status "Running SFC..." -PercentComplete 0
|
||||||
$oldpercent = 0
|
$oldpercent = 0
|
||||||
# SFC has a bug when redirected which causes it to output only when the stdout buffer is full, causing the progress bar to move in chunks
|
|
||||||
sfc.exe /scannow 2>&1 | ForEach-Object {
|
sfc.exe /scannow 2>&1 | ForEach-Object {
|
||||||
Write-Verbose $_
|
Write-Verbose $_
|
||||||
if ($_ -ne "") {
|
if ($_ -ne "") {
|
||||||
# sfc.exe /scannow outputs unicode characters, so we directly remove null characters for optimization
|
# sfc.exe /scannow outputs unicode characters, so we directly remove null characters for optimization
|
||||||
$utf8line = $_ -replace "`0", ""
|
$utf8line = $_ -replace "`0", ""
|
||||||
if ($utf8line -match "(\d+)\s%") {
|
if ($utf8line -match "(\d+)\s*%") {
|
||||||
# Write-Host "$($matches[0]) $($matches[1])"
|
|
||||||
[int]$percent = $matches[1]
|
[int]$percent = $matches[1]
|
||||||
if ($percent -gt $oldpercent) {
|
if ($percent -gt $oldpercent) {
|
||||||
Write-Progress -Id 1 -ParentId 0 -Activity "Scanning for corruption" -Status "Running SFC... ($percent%)" -PercentComplete $percent
|
Write-Progress -Id 1 -Activity $childProgressBarActivity -Status "Running SFC... ($percent%)" -PercentComplete $percent
|
||||||
$oldpercent = $percent
|
$oldpercent = $percent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Write-Progress -Id 1 -ParentId 0 -Activity "Scanning for corruption" -Status "SFC Completed" -PercentComplete 100
|
Write-Progress -Id 1 -Activity $childProgressBarActivity -Status "SFC Completed" -PercentComplete 100 -Completed
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function run_dism {
|
function Invoke-DISM {
|
||||||
<#
|
<#
|
||||||
.SYNOPSIS
|
.SYNOPSIS
|
||||||
Runs DISM on the system drive
|
Runs DISM on the system drive
|
||||||
@ -110,13 +107,14 @@ function Invoke-WPFSystemRepair {
|
|||||||
/Cleanup-Image - Performs cleanup operations on the image, could remove some unneeded temporary files
|
/Cleanup-Image - Performs cleanup operations on the image, could remove some unneeded temporary files
|
||||||
/Restorehealth - Performs a scan of the image and fixes any corruption
|
/Restorehealth - Performs a scan of the image and fixes any corruption
|
||||||
|
|
||||||
.PARAMETER verbose
|
.PARAMETER verbose
|
||||||
If specified, print output from DISM
|
If specified, print output from DISM
|
||||||
.NOTES
|
.NOTES
|
||||||
VerbosePreference is defined locally, so it only affects this function. This is done by wrapping the code inside a script block and calling it with & { ... }
|
VerbosePreference is set locally within a script block (& { ... }) to avoid affecting the global or parent scope.
|
||||||
#>
|
#>
|
||||||
param(
|
param(
|
||||||
[switch]$verbose
|
[switch]$verbose,
|
||||||
|
[int]$parentProgressId = 0
|
||||||
)
|
)
|
||||||
& {
|
& {
|
||||||
if ($verbose) {
|
if ($verbose) {
|
||||||
@ -125,41 +123,41 @@ function Invoke-WPFSystemRepair {
|
|||||||
else {
|
else {
|
||||||
$VerbosePreference = "SilentlyContinue"
|
$VerbosePreference = "SilentlyContinue"
|
||||||
}
|
}
|
||||||
|
|
||||||
Write-Progress -Id 1 -ParentId 0 -Activity "Scanning for corruption" -Status "Running DISM..." -PercentComplete 0
|
Write-Progress -Id 1 -ParentId $parentProgressId -Activity $childProgressBarActivity -Status "Running DISM..." -PercentComplete 0
|
||||||
$oldpercent = 0
|
$oldpercent = 0
|
||||||
DISM /Online /Cleanup-Image /RestoreHealth | ForEach-Object {
|
DISM /Online /Cleanup-Image /RestoreHealth | ForEach-Object {
|
||||||
Write-Verbose $_
|
Write-Verbose $_
|
||||||
|
|
||||||
# Filter for lines that contain a percentage that is greater than the previous one
|
# Filter for lines that contain a percentage that is greater than the previous one
|
||||||
if ($_ -match "(\d+)[.,]\d+%") {
|
if ($_ -match "(\d+)[.,]\d+%") {
|
||||||
[int]$percent = $matches[1]
|
[int]$percent = $matches[1]
|
||||||
if ($percent -gt $oldpercent) {
|
if ($percent -gt $oldpercent) {
|
||||||
# Update the progress bar
|
# Update the progress bar
|
||||||
Write-Progress -Id 1 -ParentId 0 -Activity "Scanning for corruption" -Status "Running DISM... ($percent%)" -PercentComplete $percent
|
Write-Progress -Id 1 -Activity $childProgressBarActivity -Status "Running DISM... ($percent%)" -PercentComplete $percent
|
||||||
$oldpercent = $percent
|
$oldpercent = $percent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Write-Progress -Id 1 -ParentId 0 -Activity "Scanning for corruption" -Status "DISM Completed" -PercentComplete 100
|
Write-Progress -Id 1 -Activity $childProgressBarActivity -Status "DISM Completed" -PercentComplete 100 -Completed
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Scan system for corruption
|
$childProgressBarActivity = "Scanning for corruption"
|
||||||
Write-Progress -Id 0 -Activity "Repairing Windows" -Status "Scanning for corruption... " -PercentComplete 0
|
Write-Progress -Id 0 -Activity "Repairing Windows" -PercentComplete 0
|
||||||
# Step 1: Run chkdsk to fix disk and filesystem corruption before proceeding with system file repairs
|
# Step 1: Run chkdsk to fix disk and filesystem corruption before proceeding with system file repairs
|
||||||
run_chkdsk
|
Invoke-Chkdsk
|
||||||
Write-Progress -Id 0 -Activity "Repairing Windows" -Status "Scanning for corruption... (25%)" -PercentComplete 25
|
Write-Progress -Id 0 -Activity "Repairing Windows" -PercentComplete 25
|
||||||
|
|
||||||
# Step 2: Run SFC to fix system file corruption and ensure DISM can operate correctly
|
# Step 2: Run SFC to fix system file corruption and ensure DISM can operate correctly
|
||||||
run_sfc
|
Invoke-SFC
|
||||||
Write-Progress -Id 0 -Activity "Repairing Windows" -Status "Scanning for corruption... (50%)" -PercentComplete 50
|
Write-Progress -Id 0 -Activity "Repairing Windows" -PercentComplete 50
|
||||||
|
|
||||||
# Step 3: Run DISM to repair the system image, which SFC relies on for accurate repairs
|
# Step 3: Run DISM to repair the system image, which SFC relies on for accurate repairs
|
||||||
run_dism
|
Invoke-DISM
|
||||||
Write-Progress -Id 0 -Activity "Repairing Windows" -Status "Scanning for corruption... (75%)" -PercentComplete 75
|
Write-Progress -Id 0 -Activity "Repairing Windows" -PercentComplete 75
|
||||||
|
|
||||||
# Step 4: Run SFC again to ensure system files are repaired using the now-fixed system image
|
# Step 4: Run SFC again to ensure system files are repaired using the now-fixed system image
|
||||||
run_sfc
|
Invoke-SFC
|
||||||
Write-Progress -Id 0 -Activity "Repairing Windows" -Status "Scanning for corruption completed" -PercentComplete 100
|
Write-Progress -Id 0 -Activity "Repairing Windows" -PercentComplete 100 -Completed
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user