diff --git a/optimization.ps1 b/optimization.ps1 index d780dc8..ee49d24 100644 --- a/optimization.ps1 +++ b/optimization.ps1 @@ -29,115 +29,87 @@ $ScriptResult = @{ } } +# Temp files for output capture $tempPath = $env:TEMP - -# Function to run process in new window with live output -function Start-ProcessWithNewWindow { - param( - [string]$FilePath, - [string]$Arguments, - [string]$Name - ) - - $stdoutFile = "$tempPath\${Name}_stdout.txt" - $stderrFile = "$tempPath\${Name}_stderr.txt" - - # Clean up old files - if (Test-Path $stdoutFile) { Remove-Item $stdoutFile -Force -ErrorAction SilentlyContinue } - if (Test-Path $stderrFile) { Remove-Item $stderrFile -Force -ErrorAction SilentlyContinue } - - Write-Host "Starting $Name in new window..." - - # Start process in new window (removed -NoNewWindow) - $process = Start-Process -FilePath $FilePath -ArgumentList $Arguments -PassThru -RedirectStandardOutput $stdoutFile -RedirectStandardError $stderrFile -ErrorAction Stop - - # Poll output files while process runs - $lastStdoutPos = 0 - $lastStderrPos = 0 - - while (-not $process.HasExited) { - Start-Sleep -Milliseconds 300 - - # Read new stdout content - if (Test-Path $stdoutFile) { - $stdoutSize = (Get-Item $stdoutFile).Length - if ($stdoutSize -gt $lastStdoutPos) { - $stream = [System.IO.File]::OpenRead($stdoutFile) - $stream.Seek($lastStdoutPos, [System.IO.SeekOrigin]::Begin) | Out-Null - $bytesToRead = $stdoutSize - $lastStdoutPos - $buffer = New-Object byte[] $bytesToRead - $stream.Read($buffer, 0, $bytesToRead) | Out-Null - $stream.Close() - $text = [System.Text.Encoding]::UTF8.GetString($buffer) - if ($text) { Write-Host $text -NoNewline } - $lastStdoutPos = $stdoutSize - } - } - - # Read new stderr content - if (Test-Path $stderrFile) { - $stderrSize = (Get-Item $stderrFile).Length - if ($stderrSize -gt $lastStderrPos) { - $stream = [System.IO.File]::OpenRead($stderrFile) - $stream.Seek($lastStderrPos, [System.IO.SeekOrigin]::Begin) | Out-Null - $bytesToRead = $stderrSize - $lastStderrPos - $buffer = New-Object byte[] $bytesToRead - $stream.Read($buffer, 0, $bytesToRead) | Out-Null - $stream.Close() - $text = [System.Text.Encoding]::UTF8.GetString($buffer) - if ($text) { Write-Host $text -NoNewline } - $lastStderrPos = $stderrSize - } - } - } - - # Wait a moment for any final output - Start-Sleep -Milliseconds 500 - - # Read final output - $outputText = "" - if (Test-Path $stdoutFile) { $outputText = Get-Content -Path $stdoutFile -Raw -ErrorAction SilentlyContinue } - if (Test-Path $stderrFile) { $outputText += Get-Content -Path $stderrFile -Raw -ErrorAction SilentlyContinue } - - # Cleanup - Remove-Item $stdoutFile -Force -ErrorAction SilentlyContinue - Remove-Item $stderrFile -Force -ErrorAction SilentlyContinue - - return @{ - ExitCode = $process.ExitCode - Output = $outputText - } -} +$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" # Run CHKDSK -Write-Host "==========================================" Write-Host "Running CHKDSK with /R option..." -Write-Host "Note: A new window will open for CHKDSK" -Write-Host "==========================================" +Write-Host "Note: If volume is in use, CHKDSK will be scheduled for next reboot." try { - $result = Start-ProcessWithNewWindow -FilePath "cmd" -Arguments "/c echo Y | chkdsk C: /R" -Name "chkdsk" - $ChkdskExitCode = $result.ExitCode - $outputText = $result.Output + # 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 + + # Read output + $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 + } + } $ScriptResult.system_optimization.chkdsk.run = $true $ScriptResult.system_optimization.chkdsk.exit_code = $ChkdskExitCode + # 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 } - switch ($ChkdskExitCode) { - 0 { $ScriptResult.system_optimization.chkdsk.success = $true; $ScriptResult.system_optimization.chkdsk.message = "CHKDSK completed successfully." } - 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." } - 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." } - default { $ScriptResult.system_optimization.chkdsk.success = $false; $ScriptResult.system_optimization.chkdsk.message = "CHKDSK completed with exit code: $ChkdskExitCode" } + # 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" + } + } + + 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)" @@ -146,29 +118,68 @@ try { } # Run SFC -Write-Host "==========================================" Write-Host "Running System File Checker (SFC /scannow)..." -Write-Host "Note: A new window will open for SFC" -Write-Host "==========================================" try { - $result = Start-ProcessWithNewWindow -FilePath "sfc" -Arguments "/scannow" -Name "sfc" - $ExitCode = $result.ExitCode - $outputText = $result.Output + $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 - switch ($ExitCode) { - 0 { $ScriptResult.system_optimization.sfc.success = $true; $ScriptResult.system_optimization.sfc.message = "SFC completed successfully."; $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." } - 3 { $ScriptResult.system_optimization.sfc.success = $false; $ScriptResult.system_optimization.sfc.message = "SFC could not fix some files."; $ScriptResult.system_optimization.sfc.files_repaired = -1 } - -1 { $ScriptResult.system_optimization.sfc.success = $false; $ScriptResult.system_optimization.sfc.message = "SFC encountered an error." } - default { $ScriptResult.system_optimization.sfc.success = $false; $ScriptResult.system_optimization.sfc.message = "SFC completed with 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)" @@ -177,35 +188,65 @@ try { } # Run DISM -Write-Host "==========================================" Write-Host "Running DISM /Online /Cleanup-Image /RestoreHealth..." -Write-Host "Note: A new window will open for DISM" -Write-Host "==========================================" try { - $result = Start-ProcessWithNewWindow -FilePath "DISM" -Arguments "/Online /Cleanup-Image /RestoreHealth" -Name "dism" - $ExitCode = $result.ExitCode - $outputText = $result.Output + $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." } - 87 { $ScriptResult.system_optimization.dism.success = $false; $ScriptResult.system_optimization.dism.message = "DISM failed. A parameter was invalid." } - 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." } + 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 exit code: $ExitCode" + $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)" @@ -213,9 +254,16 @@ try { 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 "==========================================" Write-Host "System optimization section completed." -Write-Host "==========================================" $result = $ScriptResult | ConvertTo-Json -Compress -Depth 10 Write-Output $result \ No newline at end of file