Fix a Slow Windows PC: A PowerShell Script That Works

A no-nonsense PowerShell script to speed up Windows — clears caches, optimizes drives, and flags real bottlenecks. No registry cleaners, no bloatware.

Why Your Windows PC Feels Slow — and a PowerShell Script to Actually Fix It

Every few months, my laptop starts feeling like it’s wading through mud. Apps take a beat longer to open. Explorer hangs on folders it used to render instantly. The fans spin up for no obvious reason. If you’ve been there, you know the temptation: download one of those “PC Cleaner Pro” tools with the exclamation-mark icon and hope for the best.

Don’t. Most of them are either useless, adware, or both.

The good news is that 90% of what those tools claim to do can be done in about 150 lines of PowerShell, using nothing but what ships with Windows. Below is the script I actually run on my own machines, plus an honest explanation of what each step does and — just as importantly — what it doesn’t do.

What actually slows a Windows machine down

Before touching anything, it helps to know what we’re fighting. In my experience, real-world slowness on a modern Windows box almost always comes from one of these:

  1. Disk pressure. A nearly-full system drive, or a mechanical HDD that’s gotten fragmented. SSDs don’t fragment the same way, but they still benefit from TRIM.
  2. Stale caches. Windows Update’s download folder, temp files, prefetch data, DNS cache. None of this is “bad,” but it accumulates.
  3. Startup bloat. Every app you’ve installed in the last two years politely asking to launch when you log in.
  4. Memory pressure. Something is eating your RAM. Usually Chrome. Sometimes Teams. Occasionally, genuine malware.
  5. Corrupted system files. Rare, but it happens — usually after an ungraceful shutdown or a botched update.

Notice what’s not on this list: registry “errors.” The registry-cleaner industry is built on a problem that mostly doesn’t exist on modern Windows. Leave it alone.

The script

The script does seven things, in order, and reports what it found. Every action is reversible or non-destructive — no registry edits, no service disabling, no “optimizing” settings you didn’t ask to change.

#Requires -Version 5.1

# --- Require admin ---
$principal = New-Object Security.Principal.WindowsPrincipal(
    [Security.Principal.WindowsIdentity]::GetCurrent()
)
if (-not $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
    Write-Warning "Please re-run in an elevated PowerShell."
    return
}

$ErrorActionPreference = 'SilentlyContinue'
$startTime  = Get-Date
$freeBefore = (Get-PSDrive C).Free

function Write-Step($msg) { Write-Host "`n==> $msg" -ForegroundColor Cyan }

The admin check is non-negotiable. Half of what follows touches protected paths, and silently failing on every one of them is a worse experience than just bailing out early. We also stash the free space on C: so we can tell the user how much we actually freed at the end — small thing, big difference in feeling like the script did something.

1. Clear temp files

Write-Step "Clearing temporary files"
$tempPaths = @(
    "$env:TEMP\*",
    "$env:SystemRoot\Temp\*",
    "$env:SystemRoot\Prefetch\*",
    "$env:LOCALAPPDATA\Microsoft\Windows\INetCache\*",
    "$env:LOCALAPPDATA\Microsoft\Windows\WebCache\*"
)
foreach ($p in $tempPaths) {
    Remove-Item -Path $p -Recurse -Force -ErrorAction SilentlyContinue
}

Windows is bad at cleaning up after itself. $env:TEMP in particular accumulates installer remnants forever. Prefetch is a slightly contentious inclusion — Windows uses it to speed up app launches — but it rebuilds itself on first run and can get genuinely corrupt. The gain from clearing it once in a while outweighs the one-time “first launch is slower” tax.

2. Clear the Windows Update cache

Write-Step "Clearing Windows Update cache"
Stop-Service -Name wuauserv -Force
Stop-Service -Name bits    -Force
Remove-Item -Path "$env:SystemRoot\SoftwareDistribution\Download\*" -Recurse -Force
Start-Service -Name bits
Start-Service -Name wuauserv

SoftwareDistribution\Download is where Windows stages update payloads. When an update fails (and they fail more often than Microsoft would like you to believe), the partial download sits there forever. I’ve seen this folder hit 40+ GB on machines that hadn’t been cleaned in years. Stopping wuauserv and bits before deleting is important — otherwise Windows has a file lock on half of it.

3. Flush DNS

Write-Step "Flushing DNS cache"
Clear-DnsClientCache
ipconfig /flushdns | Out-Null

Calling both Clear-DnsClientCache and ipconfig /flushdns is belt-and-suspenders — they target slightly different caches depending on your Windows version. A stale DNS cache won’t make your whole system slow, but it can make the internet feel flaky in a way that’s easy to misattribute to “the computer.”

4. Empty the Recycle Bin

Clear-RecycleBin -Force -ErrorAction SilentlyContinue

Obvious but often overlooked. The Recycle Bin is per-drive, and Clear-RecycleBin hits them all.

5. Optimize drives

Get-Volume | Where-Object { $_.DriveLetter -and $_.DriveType -eq 'Fixed' } |
    ForEach-Object {
        Optimize-Volume -DriveLetter $_.DriveLetter -Verbose:$false
    }

This is the step most people get wrong when they write their own version. Optimize-Volume is smart: it runs a defrag on spinning disks and a TRIM pass on SSDs. You don’t need to detect which is which yourself — Windows already knows. Filtering to DriveType -eq 'Fixed' keeps us from optimizing USB drives, which is slow and pointless.

6. Show what’s eating your RAM

Write-Step "Top 10 processes by memory usage"
Get-Process | Sort-Object WorkingSet -Descending |
    Select-Object -First 10 Name, Id,
        @{n='RAM (MB)'; e={[math]::Round($_.WorkingSet / 1MB, 1)}},
        @{n='CPU (s)';  e={[math]::Round($_.CPU, 1)}} |
    Format-Table -AutoSize

This is purely informational — the script doesn’t kill anything. But 90% of the time, the real answer to “why is my PC slow” is sitting in this table. When I see Chrome eating 8 GB across 40 helper processes, I have my answer, and no amount of cache-clearing is going to fix it.

7. Run SFC

sfc /scannow

System File Checker verifies the integrity of Windows system files and repairs them from a local cache if they’re damaged. It’s slow — often 5-10 minutes — and usually finds nothing. But the one time in twenty that it does find something, it’ll save you a reinstall.

The summary

$freeAfter = (Get-PSDrive C).Free
$freed     = [math]::Round(($freeAfter - $freeBefore) / 1MB, 1)
$elapsed   = (Get-Date) - $startTime

Write-Host "Finished in $([math]::Round($elapsed.TotalMinutes,1)) minutes"
Write-Host "Disk space freed on C: approximately $freed MB"

Always tell the user what happened. A script that silently succeeds feels the same as one that silently failed.

Running it

Save the script as Boost-Performance.ps1, then in an elevated PowerShell:

Set-ExecutionPolicy -Scope Process Bypass
cd $HOME\Downloads
.\Boost-Performance.ps1

The -Scope Process flag is important: it loosens execution policy for this session only, not permanently. When the window closes, you’re back to default security.

What this script deliberately does not do

It’s worth being explicit about the things I left out, because the internet is full of scripts that include them and shouldn’t:

  • Disabling services. “Superfetch is slow, disable it!” — maybe, on a 2011 laptop with a mechanical drive. On modern hardware it’s almost always a net positive. Services are a scalpel, not a hammer.
  • Tweaking the page file. Windows has been good at managing this since roughly Vista. Leave it alone.
  • Registry cleaning. As mentioned: the problem being sold is largely fictional, and the risk of breaking something real is not.
  • Ending processes automatically. Reporting them is fine. Killing them on the user’s behalf is the kind of thing that makes people distrust automation.

When the script isn’t enough

If you run this and your machine still feels slow, the honest answer is usually one of:

  • You’re out of RAM. Open Task Manager → Performance → Memory. If “In use” is consistently pinned near your total, more cleanup won’t help. Close tabs, or buy more RAM.
  • Your drive is dying. Run Get-PhysicalDisk | Select FriendlyName, HealthStatus, OperationalStatus. Anything other than Healthy/OK is a red flag.
  • You have a spinning HDD as your system drive. An SSD upgrade is the single biggest performance improvement available for any pre-2018 machine. Nothing in software comes close.
  • Something is actively malicious. Run Get-MpThreatDetection to see what Defender has caught lately, or do a full scan with Start-MpScan -ScanType FullScan.

None of those are fixable with a one-liner. But knowing which bucket you’re in is half the battle — and the script above will, at minimum, clear enough noise for the real problem to become obvious.