Private/Resolve-WUSystemPartition.ps1
function Resolve-WUSystemPartition { <# .SYNOPSIS Resolves System Reserved Partition disk space issues for Windows Update. .DESCRIPTION Mounts the System Reserved partition and performs cleanup operations to free disk space for Windows Update operations. Includes font file cleanup and manufacturer-specific optimizations. .PARAMETER LogPath Path to the log file for detailed logging. .EXAMPLE $result = Resolve-WUSystemPartition -LogPath "C:\Logs\wu.log" .NOTES This function requires Administrator privileges. Returns an object with Success, SpaceFreed, and RebootRequired properties. #> [CmdletBinding()] param( [string]$LogPath ) # Initialize result object $result = [PSCustomObject]@{ Success = $false SpaceFreed = 0 RebootRequired = $false ActionsPerformed = @() ErrorMessage = $null } Write-WULog -Message "Starting System Reserved Partition remediation" -LogPath $LogPath try { # Mount the system reserved partition to Y: Write-WULog -Message "Mounting System Reserved partition to Y:..." -LogPath $LogPath $mountResult = & cmd.exe /c "mountvol Y: /s" 2>&1 if (!(Test-Path 'Y:\')) { throw "Failed to mount System Reserved partition to Y:. Output: $mountResult" } Write-WULog -Message "System Reserved partition mounted successfully" -LogPath $LogPath # Get initial free space try { $initialSpace = (Get-CimInstance -ClassName Win32_LogicalDisk | Where-Object { $_.DeviceID -eq "Y:" }).FreeSpace Write-WULog -Message "Initial free space on System Reserved: $([math]::Round($initialSpace / 1MB, 2)) MB" -LogPath $LogPath } catch { Write-WULog -Message "Could not determine initial free space" -Level Warning -LogPath $LogPath $initialSpace = 0 } # Delete all .ttf font files in the Fonts directory $fontsPath = 'Y:\EFI\Microsoft\Boot\Fonts' if (Test-Path $fontsPath) { try { $ttfFiles = Get-ChildItem -Path $fontsPath -Filter *.ttf -ErrorAction SilentlyContinue if ($ttfFiles) { $totalSize = ($ttfFiles | Measure-Object -Property Length -Sum).Sum Write-WULog -Message "Found $($ttfFiles.Count) font files totaling $([math]::Round($totalSize / 1MB, 2)) MB" -LogPath $LogPath Remove-Item -Path "$fontsPath\*.ttf" -Force -ErrorAction Stop Write-WULog -Message "Font files deleted successfully" -LogPath $LogPath $result.ActionsPerformed += "Removed $($ttfFiles.Count) font files ($([math]::Round($totalSize / 1MB, 2)) MB)" $result.SpaceFreed += $totalSize } else { Write-WULog -Message "No .ttf files found in $fontsPath" -LogPath $LogPath } } catch { Write-WULog -Message "Error cleaning font files: $($_.Exception.Message)" -Level Warning -LogPath $LogPath } } else { Write-WULog -Message "$fontsPath does not exist" -Level Warning -LogPath $LogPath } # Handle manufacturer-specific cleanup try { $manufacturer = (Get-CimInstance -ClassName Win32_ComputerSystem).Manufacturer Write-WULog -Message "Detected Manufacturer: $manufacturer" -LogPath $LogPath switch -Wildcard ($manufacturer) { "*HP*" { $hpPath = 'Y:\EFI\HP\DEVFW' if (Test-Path $hpPath) { $hpFiles = Get-ChildItem -Path $hpPath -File -ErrorAction SilentlyContinue if ($hpFiles) { $destDir = 'C:\CSOLVE\HPDEVFW' $totalSize = ($hpFiles | Measure-Object -Property Length -Sum).Sum Write-WULog -Message "Found HP DEVFW files totaling $([math]::Round($totalSize / 1MB, 2)) MB" -LogPath $LogPath if (!(Test-Path $destDir)) { New-Item -Path $destDir -ItemType Directory -Force | Out-Null Write-WULog -Message "Created backup directory: $destDir" -LogPath $LogPath } Move-Item -Path "$hpPath\*" -Destination $destDir -Force -ErrorAction Stop Write-WULog -Message "HP DEVFW files moved successfully to $destDir" -LogPath $LogPath $result.ActionsPerformed += "Moved HP DEVFW files to backup location ($([math]::Round($totalSize / 1MB, 2)) MB)" $result.SpaceFreed += $totalSize } else { Write-WULog -Message "No files found in HP DEVFW directory" -LogPath $LogPath } } else { Write-WULog -Message "No HP DEVFW directory found" -LogPath $LogPath } } "*Dell*" { Write-WULog -Message "Dell system detected - checking for Dell-specific cleanup opportunities" -LogPath $LogPath # Check for Dell BIOS update files that might be taking space $dellPaths = @('Y:\EFI\Dell', 'Y:\Dell') foreach ($dellPath in $dellPaths) { if (Test-Path $dellPath) { $dellFiles = Get-ChildItem -Path $dellPath -File -Recurse -ErrorAction SilentlyContinue if ($dellFiles) { $totalSize = ($dellFiles | Measure-Object -Property Length -Sum).Sum if ($totalSize -gt 10MB) { # Only clean if significant space Write-WULog -Message "Found Dell files in $dellPath totaling $([math]::Round($totalSize / 1MB, 2)) MB" -LogPath $LogPath # For Dell, we'll just log but not automatically clean - could be important BIOS files Write-WULog -Message "Dell BIOS files detected but not automatically removed for safety" -Level Warning -LogPath $LogPath } } } } } "*Lenovo*" { Write-WULog -Message "Lenovo system detected - checking for Lenovo-specific cleanup opportunities" -LogPath $LogPath # Check for Lenovo UEFI files $lenovoPath = 'Y:\EFI\Lenovo' if (Test-Path $lenovoPath) { $lenovoFiles = Get-ChildItem -Path $lenovoPath -File -Recurse -ErrorAction SilentlyContinue if ($lenovoFiles) { $totalSize = ($lenovoFiles | Measure-Object -Property Length -Sum).Sum Write-WULog -Message "Found Lenovo files totaling $([math]::Round($totalSize / 1MB, 2)) MB - leaving in place for system stability" -LogPath $LogPath } } } default { Write-WULog -Message "No manufacturer-specific cleanup available for: $manufacturer" -LogPath $LogPath } } } catch { Write-WULog -Message "Error during manufacturer-specific cleanup: $($_.Exception.Message)" -Level Warning -LogPath $LogPath } # Additional cleanup - old Windows Update cache files on System Reserved try { $updateCachePaths = @( 'Y:\$Windows.~BT', 'Y:\$Windows.~WS', 'Y:\Windows.old' ) foreach ($cachePath in $updateCachePaths) { if (Test-Path $cachePath) { $cacheFiles = Get-ChildItem -Path $cachePath -Recurse -File -ErrorAction SilentlyContinue if ($cacheFiles) { $totalSize = ($cacheFiles | Measure-Object -Property Length -Sum).Sum if ($totalSize -gt 0) { Write-WULog -Message "Found old Windows Update cache in $cachePath totaling $([math]::Round($totalSize / 1MB, 2)) MB" -LogPath $LogPath # Only remove if it's actually taking significant space and is old $cacheAge = (Get-Date) - (Get-Item $cachePath).LastWriteTime if ($cacheAge.TotalDays -gt 7 -and $totalSize -gt 50MB) { Remove-Item -Path $cachePath -Recurse -Force -ErrorAction Stop Write-WULog -Message "Removed old Windows Update cache from $cachePath" -LogPath $LogPath $result.ActionsPerformed += "Removed old Windows Update cache ($([math]::Round($totalSize / 1MB, 2)) MB)" $result.SpaceFreed += $totalSize } } } } } } catch { Write-WULog -Message "Error cleaning Windows Update cache: $($_.Exception.Message)" -Level Warning -LogPath $LogPath } # Check final free space try { $finalSpace = (Get-CimInstance -ClassName Win32_LogicalDisk | Where-Object { $_.DeviceID -eq "Y:" }).FreeSpace $freedSpace = $finalSpace - $initialSpace Write-WULog -Message "Final free space on System Reserved: $([math]::Round($finalSpace / 1MB, 2)) MB" -LogPath $LogPath Write-WULog -Message "Space freed: $([math]::Round($freedSpace / 1MB, 2)) MB" -LogPath $LogPath # Update the actual space freed (may be different from file sizes due to cluster sizes) if ($freedSpace -gt 0) { $result.SpaceFreed = $freedSpace } } catch { Write-WULog -Message "Could not determine final free space" -Level Warning -LogPath $LogPath } $result.Success = $true } catch { $result.ErrorMessage = $_.Exception.Message Write-WULog -Message "Error during System Reserved partition remediation: $($_.Exception.Message)" -Level Error -LogPath $LogPath } finally { # Always attempt to unmount Write-WULog -Message "Unmounting System Reserved partition..." -LogPath $LogPath try { $unmountResult = & cmd.exe /c "mountvol Y: /d" 2>&1 Write-WULog -Message "Unmount command output: $unmountResult" -LogPath $LogPath # Give it a moment to unmount Start-Sleep -Seconds 2 if (Test-Path 'Y:\') { Write-WULog -Message "Y: drive still mounted after unmount attempt" -Level Warning -LogPath $LogPath # Try force unmount try { & cmd.exe /c "mountvol Y: /d" 2>&1 | Out-Null Start-Sleep -Seconds 1 } catch { Write-WULog -Message "Force unmount also failed" -Level Warning -LogPath $LogPath } } else { Write-WULog -Message "System Reserved partition unmounted successfully" -LogPath $LogPath } } catch { Write-WULog -Message "Error during unmount: $($_.Exception.Message)" -Level Warning -LogPath $LogPath } } # Summary if ($result.Success) { Write-WULog -Message "System Reserved Partition remediation completed successfully" -LogPath $LogPath if ($result.ActionsPerformed.Count -gt 0) { Write-WULog -Message "Actions performed:" -LogPath $LogPath foreach ($action in $result.ActionsPerformed) { Write-WULog -Message " - $action" -LogPath $LogPath } } if ($result.SpaceFreed -gt 0) { Write-WULog -Message "Total space freed: $([math]::Round($result.SpaceFreed / 1MB, 2)) MB" -LogPath $LogPath } } else { Write-WULog -Message "System Reserved Partition remediation failed: $($result.ErrorMessage)" -Level Error -LogPath $LogPath } return $result } |