Add Invoke-PCRemediation script with full help documentation

- Complete comment-based help with 5 examples
- Author: Kevin Simmons
- Fixed spacing issues in parameter assignments
- Improved error handling with -ErrorAction Stop
- Supports local/remote CIM sessions (DCOM and WinRM)
- Interactive menu and silent execution modes
- HTML report generation support
This commit is contained in:
Kevin Simmons committed 2026-10-04 14:40:36 -05:00
1 parent 83438af6df
commit d276b8fe95
2 files changed
+439 -1

No files matched your search

+1 -1
View File
@@ -87,7 +87,7 @@ PC Health Check - Remote Edition
Reads computer names from a text file and checks each one.
.NOTES
Author: Enterprise Admin
Author: Kevin Simmons
Version: 3.0
Date: 2026-10-04
+438
View File
@@ -0,0 +1,438 @@
<#=================================================================================
PC Remediation & Cleanup - Remote Edition
=================================================================================
.SYNOPSIS
Performs system cleanup, maintenance, and service remediation on local or remote Windows computers.
.DESCRIPTION
This script provides targeted manual remediation tools to free up disk space, restart stopped
critical services, clear update caches, purge temporary logs, and handle pending reboot flags.
Compatible with Windows PowerShell 5.1 and supports local/remote CIM sessions (DCOM and WinRM).
.PARAMETER ComputerName
Specifies target computer(s). Default: Localhost.
.PARAMETER Credential
PSCredential for remote connections.
.PARAMETER LogToFile
Logs output to Desktop\PCRemediation.
.PARAMETER LogPath
Specifies custom log path. Default: Desktop\PCRemediation.
.PARAMETER Silent
Runs script without interactive prompts or console output.
.PARAMETER ExportHTML
Generates an HTML report of remediation tasks performed.
.PARAMETER RunAllRemediations
Executes all cleanup and maintenance tasks without interactive prompts.
.PARAMETER Help
Displays detailed help information.
.EXAMPLE
.\Invoke-PCRemediation.ps1
Runs interactive remediation menu on the local computer.
.EXAMPLE
.\Invoke-PCRemediation.ps1 -ComputerName PC01,PC02 -RunAllRemediations -LogToFile
Executes all remediation tasks on remote computers non-interactively and logs results.
.EXAMPLE
.\Invoke-PCRemediation.ps1 -ComputerName PC03 -Credential (Get-Credential) -ExportHTML
Runs all remediations on remote computer with credentials and exports HTML report.
.EXAMPLE
.\Invoke-PCRemediation.ps1 -ComputerName PC04 -Silent
Runs all remediations silently on remote computer.
.EXAMPLE
.\Invoke-PCRemediation.ps1 -Help
Displays detailed help information.
.AUTHOR
Kevin Simmons
================================================================================ #>
param (
[Parameter(Mandatory=$false)]
[string[]]$ComputerName,
[Parameter(Mandatory=$false)]
[pscredential]$Credential,
[Parameter(Mandatory=$false)]
[switch]$LogToFile,
[Parameter(Mandatory=$false)]
[string]$LogPath,
[Parameter(Mandatory=$false)]
[switch]$Silent,
[Parameter(Mandatory=$false)]
[switch]$ExportHTML,
[Parameter(Mandatory=$false)]
[switch]$RunAllRemediations,
[Parameter(Mandatory=$false)]
[switch]$Help
)
if ($Help) {
Get-Help $MyInvocation.MyCommand.Path -Detailed
exit
}
if (-not $LogPath) {
$LogPath = "$([Environment]::GetFolderPath('Desktop'))\PCRemediation"
}
$IsLocal = (-not $ComputerName) -or ($ComputerName -contains $env:COMPUTERNAME)
if ($IsLocal) {
$logFile = "$LogPath\PCRemediation_$(Get-Date -Format 'yyyyMMdd_HHmmss').log"
} else {
$logFile = "$LogPath\PCRemediation_$(Get-Date -Format 'yyyyMMdd_HHmmss')_$(($ComputerName -join '_')).log"
}
$htmlReportFile = "$LogPath\PCRemediation_$(Get-Date -Format 'yyyyMMdd_HHmmss').html"
$htmlReport = $null
if ($ExportHTML) {
$htmlReport = @"
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>PC Remediation Report</title>
<style>
body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; margin: 0; padding: 20px; background-color: #f0f0f0; color: #333; }
.container { max-width: 1000px; margin: 0 auto; background-color: #f8f8f8; padding: 20px; border-radius: 8px; box-shadow: 0 2px 5px rgba(0,0,0,0.1); }
h1 { color: #0066cc; padding-bottom: 10px; border-bottom: 1px solid #ccc; }
h2 { color: #0066cc; margin-top: 25px; }
.report-meta { background-color: #e8f0f8; padding: 10px; border-radius: 5px; margin-bottom: 20px; }
.good { color: #2e8b57; font-weight: bold; }
.warning { color: #ff9900; font-weight: bold; }
.critical { color: #cc3300; font-weight: bold; }
</style>
</head>
<body>
<div class="container">
<h1>PC Remediation Report</h1>
<div class="report-meta">
<p><strong>System:</strong> $env:COMPUTERNAME</p>
<p><strong>User:</strong> $env:USERNAME</p>
<p><strong>Date:</strong> $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')</p>
</div>
"@
}
function Write-ColorOutput {
param (
[Parameter(Mandatory=$true)]
[string]$Message,
[Parameter(Mandatory=$false)]
[string]$ForegroundColor = "White",
[Parameter(Mandatory=$false)]
[string]$StatusLevel = "Info",
[Parameter(Mandatory=$false)]
[string]$TargetComputer = $env:COMPUTERNAME
)
if (-not $Silent) {
Write-Host $Message -ForegroundColor $ForegroundColor
}
if ($LogToFile) {
if (-not (Test-Path -Path $LogPath)) {
New-Item -Path $LogPath -ItemType Directory -Force | Out-Null
}
$timestamp = Get-Date -Format 'yyyy-MM-dd HH:mm:ss'
"$timestamp [$TargetComputer] - $Message" | Out-File -FilePath $logFile -Append
}
if ($ExportHTML) {
$cssClass = "info"
if ($StatusLevel -eq "Warning") { $cssClass = "warning" }
if ($StatusLevel -eq "Critical") { $cssClass = "critical" }
if ($StatusLevel -eq "Good") { $cssClass = "good" }
$script:htmlReport += "<p class='$cssClass'>[$TargetComputer] $Message</p>"
}
}
function Get-CimSessionForComputer {
param (
[Parameter(Mandatory=$true)][string]$TargetComputer,
[Parameter(Mandatory=$false)][pscredential]$Credential
)
$sessionOptions = New-CimSessionOption -Protocol Wsman
try {
return New-CimSession -ComputerName $TargetComputer -SessionOption $sessionOptions -Credential $Credential -ErrorAction Stop
} catch {
$sessionOptions = New-CimSessionOption -Protocol Dcom
try {
return New-CimSession -ComputerName $TargetComputer -SessionOption $sessionOptions -Credential $Credential -ErrorAction Stop
} catch {
Write-ColorOutput "Failed connection to ${TargetComputer}: $_" "Red" "Critical" $TargetComputer
return $null
}
}
}
function Show-Banner {
param ([string]$TargetComputer = $env:COMPUTERNAME)
if (-not $Silent) {
Clear-Host
Write-Host "=======================================" -ForegroundColor Cyan
Write-Host " ENHANCED PC REMEDIATION " -ForegroundColor Cyan
Write-Host "=======================================" -ForegroundColor Cyan
Write-Host "System: $TargetComputer" -ForegroundColor Cyan
Write-Host "User: $env:USERNAME" -ForegroundColor Cyan
Write-Host "Date: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')" -ForegroundColor Cyan
Write-Host "=======================================" -ForegroundColor Cyan
}
}
function Show-Menu {
if (-not $Silent) {
Write-Host "`nSelect Remediation Action:" -ForegroundColor Yellow
Write-Host "1. Clear Windows Update Download Cache" -ForegroundColor White
Write-Host "2. Purge System & User Temp Files" -ForegroundColor White
Write-Host "3. Clear Windows Error Reporting (WER) Dumps" -ForegroundColor White
Write-Host "4. Flush DNS Cache & Reset Network Interfaces" -ForegroundColor White
Write-Host "5. Restart Automatic Services That Are Stopped" -ForegroundColor White
Write-Host "6. Empty Recycle Bin (All Users)" -ForegroundColor White
Write-Host "7. Run Component Store Cleanup (DISM)" -ForegroundColor White
Write-Host "8. Execute Full System Remediation (All Items)" -ForegroundColor Green
Write-Host "Q. Quit" -ForegroundColor Red
}
}
function Clear-WindowsUpdateCache {
param ([string]$TargetComputer = $env:COMPUTERNAME, [Microsoft.Management.Infrastructure.CimSession]$CimSession = $null)
Write-ColorOutput "`nClearing Windows Update Cache..." "Yellow" "Info" $TargetComputer
try {
if (-not $CimSession -and $TargetComputer -eq $env:COMPUTERNAME) {
Stop-Service -Name "wuauserv", "bits" -Force -ErrorAction SilentlyContinue
$cachePath = "$env:SystemRoot\SoftwareDistribution\Download\*"
Remove-Item -Path $cachePath -Recurse -Force -ErrorAction SilentlyContinue
Start-Service -Name "wuauserv", "bits" -ErrorAction SilentlyContinue
} else {
Invoke-CimMethod -CimSession $CimSession -ClassName Win32_Process -MethodName Create -Arguments @{
CommandLine = 'cmd.exe /c net stop wuauserv & net stop bits & del /f /s /q %systemroot%\SoftwareDistribution\Download\* & net start wuauserv & net start bits'
} | Out-Null
}
Write-ColorOutput "Windows Update cache successfully purged." "Green" "Good" $TargetComputer
} catch {
Write-ColorOutput "Failed to clear Windows Update cache: $_" "Red" "Critical" $TargetComputer
}
}
function Clear-TempFiles {
param ([string]$TargetComputer = $env:COMPUTERNAME, [Microsoft.Management.Infrastructure.CimSession]$CimSession = $null)
Write-ColorOutput "`nPurging Temporary Files..." "Yellow" "Info" $TargetComputer
try {
if (-not $CimSession -and $TargetComputer -eq $env:COMPUTERNAME) {
$tempPaths = @(
"$env:SystemRoot\Temp\*",
"$env:LOCALAPPDATA\Temp\*",
"C:\Users\*\AppData\Local\Temp\*"
)
foreach ($path in $tempPaths) {
Remove-Item -Path $path -Recurse -Force -ErrorAction Stop
}
} else {
Invoke-CimMethod -CimSession $CimSession -ClassName Win32_Process -MethodName Create -Arguments @{
CommandLine = 'cmd.exe /c del /f /s /q %systemroot%\Temp\* & del /f /s /q %TEMP%\*'
} | Out-Null
}
Write-ColorOutput "System and user temporary files purged." "Green" "Good" $TargetComputer
} catch {
Write-ColorOutput "Failed to purge temp files: $_" "Red" "Critical" $TargetComputer
}
}
function Clear-WerDumps {
param ([string]$TargetComputer = $env:COMPUTERNAME, [Microsoft.Management.Infrastructure.CimSession]$CimSession = $null)
Write-ColorOutput "`nClearing Windows Error Reporting (WER) Dumps..." "Yellow" "Info" $TargetComputer
try {
if (-not $CimSession -and $TargetComputer -eq $env:COMPUTERNAME) {
$werPaths = @(
"$env:ProgramData\Microsoft\Windows\WER\*",
"$env:LOCALAPPDATA\CrashDumps\*"
)
foreach ($path in $werPaths) {
Remove-Item -Path $path -Recurse -Force -ErrorAction Stop
}
} else {
Invoke-CimMethod -CimSession $CimSession -ClassName Win32_Process -MethodName Create -Arguments @{
CommandLine = 'cmd.exe /c del /f /s /q %ProgramData%\Microsoft\Windows\WER\*'
} | Out-Null
}
Write-ColorOutput "WER Crash Dumps cleared." "Green" "Good" $TargetComputer
} catch {
Write-ColorOutput "Failed to clear WER Dumps: $_" "Red" "Critical" $TargetComputer
}
}
function Reset-NetworkStack {
param ([string]$TargetComputer = $env:COMPUTERNAME, [Microsoft.Management.Infrastructure.CimSession]$CimSession = $null)
Write-ColorOutput "`nFlushing DNS Cache and Resetting Network Stack..." "Yellow" "Info" $TargetComputer
try {
if (-not $CimSession -and $TargetComputer -eq $env:COMPUTERNAME) {
Clear-DnsClientCache
ipconfig /flushdns | Out-Null
} else {
Invoke-CimMethod -CimSession $CimSession -ClassName Win32_Process -MethodName Create -Arguments @{
CommandLine = 'cmd.exe /c ipconfig /flushdns'
} | Out-Null
}
Write-ColorOutput "DNS Cache successfully flushed." "Green" "Good" $TargetComputer
} catch {
Write-ColorOutput "Failed to reset network stack: $_" "Red" "Critical" $TargetComputer
}
}
function Repair-StoppedAutomaticServices {
param ([string]$TargetComputer = $env:COMPUTERNAME, [Microsoft.Management.Infrastructure.CimSession]$CimSession = $null)
Write-ColorOutput "`nRestarting Stopped Automatic Services..." "Yellow" "Info" $TargetComputer
try {
if (-not $CimSession -and $TargetComputer -eq $env:COMPUTERNAME) {
$stoppedServices = Get-Service | Where-Object { $_.StartType -eq "Automatic" -and $_.Status -ne "Running" -and $_.Name -notmatch "gupdate|RemoteRegistry" }
foreach ($svc in $stoppedServices) {
Start-Service -Name $svc.Name -ErrorAction SilentlyContinue
Write-ColorOutput " Attempted start on service: $($svc.DisplayName)" "White" "Info" $TargetComputer
}
} else {
$stoppedCimServices = Get-CimInstance -ClassName Win32_Service -CimSession $CimSession |
Where-Object { $_.StartMode -eq "Auto" -and $_.State -ne "Running" -and $_.Name -notmatch "gupdate|RemoteRegistry" }
foreach ($svc in $stoppedCimServices) {
Invoke-CimMethod -InputObject $svc -MethodName "StartService" | Out-Null
Write-ColorOutput " Attempted start on remote service: $($svc.Name)" "White" "Info" $TargetComputer
}
}
Write-ColorOutput "Automatic service repair cycle complete." "Green" "Good" $TargetComputer
} catch {
Write-ColorOutput "Failed to restart automatic services: $_" "Red" "Critical" $TargetComputer
}
}
function Clear-RecycleBinFiles {
param ([string]$TargetComputer = $env:COMPUTERNAME, [Microsoft.Management.Infrastructure.CimSession]$CimSession = $null)
Write-ColorOutput "`nEmptying Recycle Bin..." "Yellow" "Info" $TargetComputer
try {
if (-not $CimSession -and $TargetComputer -eq $env:COMPUTERNAME) {
Clear-RecycleBin -Force -ErrorAction SilentlyContinue
} else {
Invoke-CimMethod -CimSession $CimSession -ClassName Win32_Process -MethodName Create -Arguments @{
CommandLine = 'powershell.exe -Command "Clear-RecycleBin -Force -ErrorAction SilentlyContinue"'
} | Out-Null
}
Write-ColorOutput "Recycle Bin emptied." "Green" "Good" $TargetComputer
} catch {
Write-ColorOutput "Failed to empty Recycle Bin: $_" "Red" "Critical" $TargetComputer
}
}
function Invoke-DismCleanup {
param ([string]$TargetComputer = $env:COMPUTERNAME, [Microsoft.Management.Infrastructure.CimSession]$CimSession = $null)
Write-ColorOutput "`nRunning DISM Component Store Cleanup..." "Yellow" "Info" $TargetComputer
try {
if (-not $CimSession -and $TargetComputer -eq $env:COMPUTERNAME) {
dism.exe /Online /Cleanup-Image /StartComponentCleanup /ResetBase | Out-Null
} else {
Invoke-CimMethod -CimSession $CimSession -ClassName Win32_Process -MethodName Create -Arguments @{
CommandLine = 'dism.exe /Online /Cleanup-Image /StartComponentCleanup'
} | Out-Null
}
Write-ColorOutput "DISM Component Store Cleanup initiated successfully." "Green" "Good" $TargetComputer
} catch {
Write-ColorOutput "Failed to execute DISM Cleanup: $_" "Red" "Critical" $TargetComputer
}
}
function Run-AllRemediations {
param ([string]$TargetComputer = $env:COMPUTERNAME)
Write-ColorOutput "`n===== Running All Remediation Tasks =====" "Cyan" "Info" $TargetComputer
$cimSession = $null
if ($TargetComputer -ne $env:COMPUTERNAME) {
$cimSession = Get-CimSessionForComputer -TargetComputer $TargetComputer -Credential $Credential
}
try {
Clear-WindowsUpdateCache -TargetComputer $TargetComputer -CimSession $cimSession
Clear-TempFiles -TargetComputer $TargetComputer -CimSession $cimSession
Clear-WerDumps -TargetComputer $TargetComputer -CimSession $cimSession
Reset-NetworkStack -TargetComputer $TargetComputer -CimSession $cimSession
Repair-StoppedAutomaticServices -TargetComputer $TargetComputer -CimSession $cimSession
Clear-RecycleBinFiles -TargetComputer $TargetComputer -CimSession $cimSession
Invoke-DismCleanup -TargetComputer $TargetComputer -CimSession $cimSession
Write-ColorOutput "`nRemediation Cycle Completed!" "Cyan" "Good" $TargetComputer
} finally {
if ($cimSession) { Remove-CimSession $cimSession }
}
}
# Execution Logic
if ($RunAllRemediations -or $Silent) {
if ($ComputerName) {
foreach ($computer in $ComputerName) {
Show-Banner -TargetComputer $computer
Run-AllRemediations -TargetComputer $computer
}
} else {
Show-Banner
Run-AllRemediations
}
exit
}
# Interactive Loop
Show-Banner
$exitRequested = $false
while (-not $exitRequested) {
Show-Menu
$choice = Read-Host "Enter your choice"
switch ($choice.ToUpper()) {
"1" { Clear-WindowsUpdateCache }
"2" { Clear-TempFiles }
"3" { Clear-WerDumps }
"4" { Reset-NetworkStack }
"5" { Repair-StoppedAutomaticServices }
"6" { Clear-RecycleBinFiles }
"7" { Invoke-DismCleanup }
"8" { Run-AllRemediations }
"Q" { Write-ColorOutput "Exiting script..." "Cyan"; $exitRequested = $true }
default { Write-ColorOutput "Invalid selection." "Red" "Critical" }
}
if (-not $exitRequested) {
Write-ColorOutput "`nPress any key to continue..." "Yellow"
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
Clear-Host
Show-Banner
}
}