This commit is contained in:
Joeri 2026-02-21 15:48:04 +01:00
parent 02d9cc72ca
commit 0c6e1c2367

View file

@ -1,269 +1,73 @@
$ScriptResult = @{
success = $true
system_optimization = @{
"chkdsk" = @{
"run" = $false
"success" = $false
"exit_code" = $null
"message" = ""
"reboot_required" = $false
"diskSpace" = ""
"errors" = @()
}
"sfc" = @{
"run" = $false
"success" = $false
"exit_code" = $null
"message" = ""
"files_repaired" = 0
"errors" = @()
}
"dism" = @{
"run" = $false
"success" = $false
"exit_code" = $null
"message" = ""
"component_repaired" = $false
"errors" = @()
}
}
}
# Function to run process with true live streaming output
function Start-ProcessWithLiveStreaming {
param(
[string]$FilePath,
[string]$Arguments,
[string]$Name
)
# Temp files for output capture
$tempPath = $env:TEMP
$chkdskStdout = "$tempPath\chkdsk_stdout.txt"
$chkdskStderr = "$tempPath\chkdsk_stderr.txt"
$sfcStdout = "$tempPath\sfc_stdout.txt"
$sfcStderr = "$tempPath\sfc_stderr.txt"
$dismStdout = "$tempPath\dism_stdout.txt"
$dismStderr = "$tempPath\dism_stderr.txt"
$stdoutFile = "$tempPath\${Name}_stdout.txt"
$stderrFile = "$tempPath\${Name}_stderr.txt"
# Run CHKDSK
Write-Host "Running CHKDSK with /R option..."
Write-Host "Note: If volume is in use, CHKDSK will be scheduled for next reboot."
# Clean up old files
if (Test-Path $stdoutFile) { Remove-Item $stdoutFile -ErrorAction SilentlyContinue }
if (Test-Path $stderrFile) { Remove-Item $stderrFile -ErrorAction SilentlyContinue }
try {
# Use cmd /c with echo Y piped, redirect output
$process = Start-Process -FilePath "cmd" -ArgumentList "/c", "echo Y | chkdsk C: /R" -NoNewWindow -Wait -PassThru -RedirectStandardOutput $chkdskStdout -RedirectStandardError $chkdskStderr -ErrorAction Stop
$ChkdskExitCode = $process.ExitCode
# Create file handles for immediate reading
$fileStream = [System.IO.File]::Create($stdoutFile)
# Read output
Write-Host "Starting $Name..."
# Start the process
$process = Start-Process -FilePath $FilePath -ArgumentList $Arguments -NoNewWindow -PassThru -RedirectStandardOutput $stdoutFile -RedirectStandardError $stderrFile -ErrorAction Stop
# Read output while process runs
$lastPosition = 0
while (-not $process.HasExited) {
Start-Sleep -Milliseconds 500
if (Test-Path $stdoutFile) {
$currentLength = (Get-Item $stdoutFile).Length
if ($currentLength -gt $lastPosition) {
$bytesToRead = $currentLength - $lastPosition
$stream = [System.IO.File]::OpenRead($stdoutFile)
$stream.Seek($lastPosition, [System.IO.SeekOrigin]::Begin) | Out-Null
$buffer = New-Object byte[] $bytesToRead
$stream.Read($buffer, 0, $bytesToRead) | Out-Null
$stream.Close()
$text = [System.Text.Encoding]::UTF8.GetString($buffer)
Write-Host $text -NoNewline
$lastPosition = $currentLength
}
}
}
# Wait for process to complete
$process.WaitForExit()
# Read any remaining output
if (Test-Path $stdoutFile) {
$content = Get-Content -Path $stdoutFile -Raw -ErrorAction SilentlyContinue
if ($content) { Write-Host $content }
}
if (Test-Path $stderrFile) {
$content = Get-Content -Path $stderrFile -Raw -ErrorAction SilentlyContinue
if ($content) { Write-Host $content }
}
# Get output for return
$outputText = ""
if (Test-Path $chkdskStdout) {
$outputText = Get-Content -Path $chkdskStdout -Raw -ErrorAction SilentlyContinue
}
if (Test-Path $chkdskStderr) {
$stderrText = Get-Content -Path $chkdskStderr -Raw -ErrorAction SilentlyContinue
if ($stderrText) {
$outputText += $stderrText
}
}
if (Test-Path $stdoutFile) { $outputText = Get-Content -Path $stdoutFile -Raw -ErrorAction SilentlyContinue }
if (Test-Path $stderrFile) { $outputText += Get-Content -Path $stderrFile -Raw -ErrorAction SilentlyContinue }
$ScriptResult.system_optimization.chkdsk.run = $true
$ScriptResult.system_optimization.chkdsk.exit_code = $ChkdskExitCode
# Cleanup
Remove-Item $stdoutFile -ErrorAction SilentlyContinue
Remove-Item $stderrFile -ErrorAction SilentlyContinue
$fileStream.Close()
# Parse output
if ($outputText -match "will be checked on next boot|Chkdsk cannot run because the volume is in use") {
$ScriptResult.system_optimization.chkdsk.reboot_required = $true
}
# Parse disk space freed (if available in output)
if ($outputText -match "(\d+) bytes in (\d+) data streams recovered") {
$bytesRecovered = [int64]$matches[1]
$ScriptResult.system_optimization.chkdsk.diskSpace = "{0:N2} MB" -f ($bytesRecovered / 1MB)
}
# Parse exit codes
switch ($ChkdskExitCode) {
0 {
$ScriptResult.system_optimization.chkdsk.success = $true
$ScriptResult.system_optimization.chkdsk.message = "CHKDSK completed successfully. No errors found."
}
1 {
$ScriptResult.system_optimization.chkdsk.success = $true
$ScriptResult.system_optimization.chkdsk.message = "CHKDSK completed successfully. Errors corrected."
}
2 {
$ScriptResult.system_optimization.chkdsk.success = $false
$ScriptResult.system_optimization.chkdsk.message = "CHKDSK did not run due to a parameter error."
}
3 {
$ScriptResult.system_optimization.chkdsk.success = $true
$ScriptResult.system_optimization.chkdsk.reboot_required = $true
$ScriptResult.system_optimization.chkdsk.message = "CHKDSK completed with errors and requires a reboot to complete."
}
4 {
$ScriptResult.system_optimization.chkdsk.success = $false
$ScriptResult.system_optimization.chkdsk.message = "CHKDSK encountered errors but could not fix them."
}
5 {
$ScriptResult.system_optimization.chkdsk.success = $false
$ScriptResult.system_optimization.chkdsk.reboot_required = $true
$ScriptResult.system_optimization.chkdsk.message = "CHKDSK found errors but requires a reboot to fix them."
}
default {
$ScriptResult.system_optimization.chkdsk.success = $false
$ScriptResult.system_optimization.chkdsk.message = "CHKDSK completed with exit code: $ChkdskExitCode"
return @{
ExitCode = $process.ExitCode
Output = $outputText
}
}
Write-Host $outputText
Write-Host "CHKDSK exit code: $ChkdskExitCode"
Write-Host "CHKDSK message: $($ScriptResult.system_optimization.chkdsk.message)"
} catch {
$ErrorMsg = "Failed to run CHKDSK: $($_.Exception.Message)"
$ScriptResult.system_optimization.chkdsk.errors += $ErrorMsg
Write-Host $ErrorMsg
}
# Run SFC
Write-Host "Running System File Checker (SFC /scannow)..."
try {
$process = Start-Process -FilePath "sfc" -ArgumentList "/scannow" -NoNewWindow -Wait -PassThru -RedirectStandardOutput $sfcStdout -RedirectStandardError $sfcStderr -ErrorAction Stop
$ExitCode = $process.ExitCode
# Read output
$outputText = ""
if (Test-Path $sfcStdout) {
$outputText = Get-Content -Path $sfcStdout -Raw -ErrorAction SilentlyContinue
}
if (Test-Path $sfcStderr) {
$stderrText = Get-Content -Path $sfcStderr -Raw -ErrorAction SilentlyContinue
if ($stderrText) {
$outputText += $stderrText
}
}
$ScriptResult.system_optimization.sfc.run = $true
$ScriptResult.system_optimization.sfc.exit_code = $ExitCode
# Parse files repaired from output
if ($outputText -match "Windows Resource Protection found integrity violations|found corrupt files and repaired them") {
if ($outputText -match "repairing corrupted files") {
$ScriptResult.system_optimization.sfc.files_repaired = 1
}
}
# Parse exit codes
switch ($ExitCode) {
0 {
$ScriptResult.system_optimization.sfc.success = $true
$ScriptResult.system_optimization.sfc.message = "SFC completed successfully. No integrity violations found."
$ScriptResult.system_optimization.sfc.files_repaired = 0
}
1 {
$ScriptResult.system_optimization.sfc.success = $true
$ScriptResult.system_optimization.sfc.message = "SFC completed successfully. Corrupted files were repaired."
$ScriptResult.system_optimization.sfc.files_repaired = 1
}
2 {
$ScriptResult.system_optimization.sfc.success = $false
$ScriptResult.system_optimization.sfc.message = "SFC could not perform the operation. User cancelled or Windows is in safe mode."
}
3 {
$ScriptResult.system_optimization.sfc.success = $false
$ScriptResult.system_optimization.sfc.message = "SFC could not fix some files. See CBS.log for details."
$ScriptResult.system_optimization.sfc.files_repaired = -1
}
-1 {
$ScriptResult.system_optimization.sfc.success = $false
$ScriptResult.system_optimization.sfc.message = "SFC encountered an error. Check CBS.log for details."
}
default {
$ScriptResult.system_optimization.sfc.success = $false
$ScriptResult.system_optimization.sfc.message = "SFC completed with unexpected exit code: $ExitCode"
}
}
Write-Host $outputText
Write-Host "SFC exit code: $ExitCode"
Write-Host "SFC message: $($ScriptResult.system_optimization.sfc.message)"
} catch {
$ErrorMsg = "Failed to run SFC: $($_.Exception.Message)"
$ScriptResult.system_optimization.sfc.errors += $ErrorMsg
Write-Host $ErrorMsg
}
# Run DISM
Write-Host "Running DISM /Online /Cleanup-Image /RestoreHealth..."
try {
$process = Start-Process -FilePath "DISM" -ArgumentList "/Online /Cleanup-Image /RestoreHealth" -NoNewWindow -Wait -PassThru -RedirectStandardOutput $dismStdout -RedirectStandardError $dismStderr -ErrorAction Stop
$ExitCode = $process.ExitCode
# Read output
$outputText = ""
if (Test-Path $dismStdout) {
$outputText = Get-Content -Path $dismStdout -Raw -ErrorAction SilentlyContinue
}
if (Test-Path $dismStderr) {
$stderrText = Get-Content -Path $dismStderr -Raw -ErrorAction SilentlyContinue
if ($stderrText) {
$outputText += $stderrText
}
}
$ScriptResult.system_optimization.dism.run = $true
$ScriptResult.system_optimization.dism.exit_code = $ExitCode
# Parse exit codes
switch ($ExitCode) {
0 {
$ScriptResult.system_optimization.dism.success = $true
$ScriptResult.system_optimization.dism.component_repaired = $true
$ScriptResult.system_optimization.dism.message = "DISM completed successfully. The component store was repaired."
}
87 {
$ScriptResult.system_optimization.dism.success = $false
$ScriptResult.system_optimization.dism.message = "DISM failed. A parameter was invalid. Check the command syntax."
}
3010 {
$ScriptResult.system_optimization.dism.success = $true
$ScriptResult.system_optimization.dism.component_repaired = $true
$ScriptResult.system_optimization.dism.message = "DISM completed successfully. A reboot is required."
}
1726 {
$ScriptResult.system_optimization.dism.success = $false
$ScriptResult.system_optimization.dism.message = "DISM failed. The remote procedure call failed."
}
1910 {
$ScriptResult.system_optimization.dism.success = $false
$ScriptResult.system_optimization.dism.message = "DISM failed. The specified image file could not be found."
}
default {
if ($ExitCode -ge 0 -and $ExitCode -le 100) {
$ScriptResult.system_optimization.dism.success = $true
$ScriptResult.system_optimization.dism.message = "DISM completed with exit code: $ExitCode"
} else {
$ScriptResult.system_optimization.dism.success = $false
$ScriptResult.system_optimization.dism.message = "DISM completed with unexpected exit code: $ExitCode"
}
}
}
Write-Host $outputText
Write-Host "DISM exit code: $ExitCode"
Write-Host "DISM message: $($ScriptResult.system_optimization.dism.message)"
} catch {
$ErrorMsg = "Failed to run DISM: $($_.Exception.Message)"
$ScriptResult.system_optimization.dism.errors += $ErrorMsg
Write-Host $ErrorMsg
}
# Cleanup temp files
Write-Host "Cleaning up temporary files..."
$tempFiles = @($chkdskStdout, $chkdskStderr, $sfcStdout, $sfcStderr, $dismStdout, $dismStderr)
foreach ($file in $tempFiles) {
if (Test-Path $file) {
Remove-Item $file -ErrorAction SilentlyContinue
}
}
# Output JSON result
Write-Host "System optimization section completed."
$result = $ScriptResult | ConvertTo-Json -Compress -Depth 10
Write-Output $result