Skip to main content

How to Run Disk Cleanup (cleanmgr) Silently in Batch Script

Maintaining sufficient disk space is a core responsibility for system administration. The Windows Disk Cleanup utility (cleanmgr.exe) removes temporary files, system logs, cached data, and other unnecessary files. However, by default it opens a GUI that requires manual interaction. By pre-configuring cleanup categories through the registry and using the /sagerun switch, a Batch script can trigger Disk Cleanup silently, enabling automated background maintenance.

This guide explains how to configure, execute, and schedule silent disk cleanup operations.

How Silent Disk Cleanup Works

  • Normal cleanmgr:

    • cleanmgr.exe
    • GUI opens
    • User selects categories
    • User clicks OK
    • Cleanup runs
  • Silent cleanmgr (two-phase approach):

    • Phase 1 (one-time setup): Configure categories

      • Run: cleanmgr /sageset:100 → opens GUI for selection
      • OR configure via registry keys (fully automated)
    • Phase 2 (repeated execution): Run cleanup silently

      • Run: cleanmgr /sagerun:100 → no GUI, uses saved settings

The key concept is Sageset/Sagerun IDs. Each ID (a number from 1 to 65535) stores a set of cleanup categories in the registry. You configure the ID once, then run it repeatedly without any user interaction.

Administrative Privileges

Many cleanup categories (Temporary Files, Internet Cache) work as a standard user. However, system-level cleanup (Windows Update files, Component Store, Memory Dumps) requires administrator privileges. For complete cleanup, always run as Administrator.

Method 1: Fully Automated Silent Cleanup (Registry-Based)

This method configures the cleanup categories directly through the registry, no manual GUI interaction required. It can be deployed to any machine without a one-time setup step.

Implementation

@echo off
setlocal

set "SageID=100"

echo ============================================================
echo Silent Disk Cleanup Utility
echo ============================================================
echo.

:: Check for admin rights
net session >nul 2>&1
if errorlevel 1 (
echo [ERROR] Administrator privileges required for system-level cleanup. >&2
echo Right-click and select "Run as administrator." >&2
endlocal
exit /b 1
)

:: Record disk space before cleanup
for /f "delims=" %%f in (
'powershell -NoProfile -Command ^
"$drive = Get-CimInstance Win32_LogicalDisk -Filter ''DeviceID=''''C:''''';" ^
"[math]::Round($drive.FreeSpace / 1GB, 2)"'
) do set "FreeBeforeGB=%%f"

echo [INFO] Free space before cleanup: %FreeBeforeGB% GB
echo.

:: =============================================
:: Configure cleanup categories via registry
:: =============================================
echo [INFO] Configuring cleanup categories...

set "RegKey=HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches"

:: Define all cleanup categories to enable
:: StateFlags followed by the SageID number, value 2 = enabled
for %%c in (
"Active Setup Temp Folders"
"BranchCache"
"Delivery Optimization Files"
"Device Driver Packages"
"Downloaded Program Files"
"Internet Cache Files"
"Memory Dump Files"
"Old ChkDsk Files"
"Previous Installations"
"Recycle Bin"
"RetailDemo Offline Content"
"Service Pack Cleanup"
"Setup Log Files"
"System error memory dump files"
"System error minidump files"
"Temporary Files"
"Temporary Setup Files"
"Thumbnail Cache"
"Update Cleanup"
"Upgrade Discarded Files"
"User file versions"
"Windows Defender"
"Windows Error Reporting Archive Files"
"Windows Error Reporting Queue Files"
"Windows Error Reporting System Archive Files"
"Windows Error Reporting System Queue Files"
"Windows ESD installation files"
"Windows Upgrade Log Files"
) do (
reg add "%RegKey%\%%~c" /v StateFlags0%SageID% /t REG_DWORD /d 2 /f >nul 2>&1
)

echo [OK] Cleanup categories configured.
echo.

:: =============================================
:: Execute the silent cleanup
:: =============================================
echo [ACTION] Running Disk Cleanup (this may take several minutes^)...
echo [INFO] cleanmgr runs in the background. A progress window may briefly appear.
echo.

cleanmgr /sagerun:%SageID%

:: Wait for cleanmgr to finish (it spawns a child process)
echo [INFO] Waiting for cleanup to complete...
:WaitLoop
timeout /t 5 >nul
tasklist /fi "IMAGENAME eq cleanmgr.exe" 2>nul | findstr /i "cleanmgr" >nul
if not errorlevel 1 goto :WaitLoop

:: Also wait for DismHost if Windows Update cleanup is running
tasklist /fi "IMAGENAME eq DismHost.exe" 2>nul | findstr /i "DismHost" >nul
if not errorlevel 1 (
echo [INFO] Windows Update cleanup is running (DismHost.exe^)...
echo [INFO] This can take 10-30 minutes for large update histories.
:DismWait
timeout /t 10 >nul
tasklist /fi "IMAGENAME eq DismHost.exe" 2>nul | findstr /i "DismHost" >nul
if not errorlevel 1 goto :DismWait
)

echo.

:: =============================================
:: Measure results
:: =============================================
for /f "delims=" %%f in (
'powershell -NoProfile -Command ^
"$drive = Get-CimInstance Win32_LogicalDisk -Filter ''DeviceID=''''C:''''';" ^
"[math]::Round($drive.FreeSpace / 1GB, 2)"'
) do set "FreeAfterGB=%%f"

echo [OK] Cleanup complete.
echo Free space before: %FreeBeforeGB% GB
echo Free space after: %FreeAfterGB% GB

for /f "delims=" %%s in (
'powershell -NoProfile -Command "[math]::Round(%FreeAfterGB% - %FreeBeforeGB%, 2)"'
) do echo Space recovered: %%s GB

echo.
echo ============================================================

:: Log the operation
for /f "delims=" %%t in (
'powershell -NoProfile -Command "Get-Date -Format ''yyyy-MM-dd HH:mm:ss''"'
) do echo [%%t] CLEANUP: Before=%FreeBeforeGB%GB After=%FreeAfterGB%GB on %COMPUTERNAME% >> "%~dp0disk_cleanup.log"

endlocal
exit /b 0

Cleanup categories explained:

CategoryWhat It RemovesTypical Size
Temporary FilesUser and system temp files100 MB – 5 GB
Internet Cache FilesBrowser cache (IE/Edge)50 MB – 2 GB
Recycle BinDeleted files awaiting permanent removalVaries widely
Windows Update CleanupOld Windows Update files1 – 10 GB
Previous InstallationsWindows.old folder from upgrades10 – 30 GB
Windows ESD installation filesDownloaded upgrade files3 – 8 GB
Memory Dump FilesSystem crash dumps1 – 16 GB per dump
Thumbnail CacheExplorer thumbnail database50 – 500 MB
Windows Error ReportingError report queues and archives50 MB – 1 GB
Delivery Optimization FilesWindows Update sharing cache100 MB – 5 GB
Some Categories Take a Very Long Time

Windows Update Cleanup and Previous Installations cleanup can take 30–60 minutes on systems with large update histories. These operations use DismHost.exe internally, which is CPU and I/O intensive. Avoid running during work hours or heavy workloads. The script monitors DismHost.exe and waits for it to finish.

Why the script waits for cleanmgr.exe and DismHost.exe:

cleanmgr /sagerun returns to the command prompt immediately while cleanup continues in the background. The script monitors the process list to detect when cleanup actually finishes, essential for accurate space-recovered measurements and for ensuring the script doesn't exit while intensive operations (like Windows Update cleanup) are still running.

Registry key format:

The registry key name follows the pattern StateFlags + four-digit zero-padded ID number:

  • /sagerun:100StateFlags0100
  • /sagerun:1StateFlags0001
  • /sagerun:65535StateFlags65535

The value 2 means "enabled for this cleanup profile." Value 0 or absent means "disabled."

Method 2: Interactive Setup + Silent Execution

For environments where you want to manually choose cleanup categories once (using the GUI), then run the selected categories silently on a schedule.

Step 1: One-time configuration (interactive)

@echo off
echo [SETUP] Opening Disk Cleanup configuration...
echo [INFO] Select all categories you want included in automated cleanup.
echo [INFO] Click OK when done. This saves the configuration for future silent runs.
echo.

cleanmgr /sageset:200

echo [OK] Configuration saved as profile 200.
echo [INFO] Run silent cleanup anytime with: cleanmgr /sagerun:200

Step 2: Silent execution (repeated)

@echo off
setlocal

echo [ACTION] Running configured Disk Cleanup (profile 200^)...

cleanmgr /sagerun:200

:: Monitor completion
:WaitClean
timeout /t 5 >nul
tasklist /fi "IMAGENAME eq cleanmgr.exe" 2>nul | findstr /i "cleanmgr" >nul
if not errorlevel 1 goto :WaitClean

echo [OK] Disk Cleanup complete.

endlocal
exit /b 0

When to use Method 1 vs. Method 2:

ScenarioMethod
Deploy to many machines without manual setupMethod 1 (registry-based)
Administrator wants to hand-pick categoriesMethod 2 (GUI setup + silent run)
Custom categories per machine typeMethod 2 (different setups on different machine roles)
Fully unattended automationMethod 1

Method 3: Additional Cleanup Beyond cleanmgr

cleanmgr doesn't cover everything. This method adds commonly needed cleanup tasks that cleanmgr doesn't handle.

@echo off
setlocal

net session >nul 2>&1
if errorlevel 1 (
echo [ERROR] Administrator privileges required. >&2
endlocal
exit /b 1
)

echo [INFO] Extended cleanup (beyond cleanmgr^)...
echo.

:: 1. Clear Windows Temp folder
echo [ACTION] Clearing Windows Temp folder...
del /q /f "%SystemRoot%\Temp\*" 2>nul
for /d %%d in ("%SystemRoot%\Temp\*") do rd /s /q "%%d" 2>nul
echo [OK] Windows Temp cleared.

:: 2. Clear user Temp folder
echo [ACTION] Clearing User Temp folder...
del /q /f "%TEMP%\*" 2>nul
for /d %%d in ("%TEMP%\*") do rd /s /q "%%d" 2>nul
echo [OK] User Temp cleared.

:: 3. Clear Windows Prefetch (improves startup after major changes)
echo [ACTION] Clearing Prefetch cache...
del /q /f "%SystemRoot%\Prefetch\*" 2>nul
echo [OK] Prefetch cleared.

:: 4. Clear font cache (fixes font display issues)
echo [ACTION] Clearing Font Cache...
net stop FontCache >nul 2>&1
del /q "%SystemRoot%\ServiceProfiles\LocalService\AppData\Local\FontCache\*" 2>nul
net start FontCache >nul 2>&1
echo [OK] Font Cache cleared.

:: 5. Flush DNS cache
ipconfig /flushdns >nul 2>&1
echo [OK] DNS cache flushed.

:: 6. Clear Windows Update download cache
echo [ACTION] Clearing Windows Update download cache...
net stop wuauserv >nul 2>&1
del /q /f "%SystemRoot%\SoftwareDistribution\Download\*" 2>nul
for /d %%d in ("%SystemRoot%\SoftwareDistribution\Download\*") do rd /s /q "%%d" 2>nul
net start wuauserv >nul 2>&1
echo [OK] Windows Update cache cleared.

echo.
echo [DONE] Extended cleanup complete.

endlocal
exit /b 0
Prefetch and Font Cache Clearing

Clearing the Prefetch cache causes a temporary slowdown in application launches as Windows rebuilds its optimization data. The Font Cache service restart may cause a brief font display glitch. These are self-healing and resolve after a few minutes. Avoid clearing these during active user sessions.

Method 4: Scheduled Maintenance Cleanup

Combine cleanmgr with extended cleanup into a single maintenance script, scheduled to run weekly during off-hours.

@echo off
setlocal

set "LogFile=%~dp0cleanup_maintenance.log"

net session >nul 2>&1
if errorlevel 1 (
echo [ERROR] Administrator privileges required. >&2
endlocal
exit /b 1
)

for /f "delims=" %%t in (
'powershell -NoProfile -Command "Get-Date -Format ''yyyy-MM-dd HH:mm:ss''"'
) do set "StartTime=%%t"

echo [%StartTime%] Maintenance cleanup started on %COMPUTERNAME% >> "%LogFile%"

:: Record space before
for /f "delims=" %%f in (
'powershell -NoProfile -Command ^
"[math]::Round((Get-CimInstance Win32_LogicalDisk -Filter ''DeviceID=''''C:''''').FreeSpace / 1GB, 2)"'
) do set "BeforeGB=%%f"

:: Phase 1: cleanmgr silent cleanup
echo [1/2] Running cleanmgr silent cleanup...
call "%~dp0silent_cleanup.bat" >nul 2>&1

:: Phase 2: Extended cleanup
echo [2/2] Running extended cleanup...
call "%~dp0extended_cleanup.bat" >nul 2>&1

:: Record space after
for /f "delims=" %%f in (
'powershell -NoProfile -Command ^
"[math]::Round((Get-CimInstance Win32_LogicalDisk -Filter ''DeviceID=''''C:''''').FreeSpace / 1GB, 2)"'
) do set "AfterGB=%%f"

for /f "delims=" %%s in (
'powershell -NoProfile -Command "[math]::Round(%AfterGB% - %BeforeGB%, 2)"'
) do set "RecoveredGB=%%s"

for /f "delims=" %%t in (
'powershell -NoProfile -Command "Get-Date -Format ''yyyy-MM-dd HH:mm:ss''"'
) do set "EndTime=%%t"

echo [%EndTime%] Complete. Before: %BeforeGB%GB After: %AfterGB%GB Recovered: %RecoveredGB%GB >> "%LogFile%"

echo [OK] Maintenance cleanup complete. Recovered %RecoveredGB% GB.

endlocal
exit /b 0

Scheduling:

:: Run weekly on Sunday at 2:00 AM
schtasks /create /tn "WeeklyDiskCleanup" /tr "\"%~dp0maintenance_cleanup.bat\"" /sc weekly /d SUN /st 02:00 /ru System /rl highest /f
Modern Alternative: Storage Sense

Windows 10/11 includes Storage Sense, which automatically cleans temp files, Recycle Bin, and Downloads folder content. It can be configured via Settings or Group Policy. However, cleanmgr provides more granular control over specific categories and integrates better with Batch automation. For comprehensive cleanup, use both: Storage Sense for continuous background cleanup and cleanmgr scripts for periodic deep cleanup.

How to Avoid Common Errors

Wrong Way: Running /sagerun Without Prior Configuration

:: Does nothing useful - no categories have been selected for ID 99
cleanmgr /sagerun:99

If the StateFlags registry keys for the specified ID don't exist, cleanmgr /sagerun runs but cleans nothing. The command appears to succeed but removes zero files.

Correct Way: Either configure via GUI (/sageset:99) first, or set the registry keys programmatically (Method 1) before calling /sagerun.

Wrong Way: Using > to Redirect cleanmgr Output

:: cleanmgr is a GUI application - its output cannot be redirected
cleanmgr /sagerun:100 > cleanup_log.txt
:: The log file will be empty

cleanmgr.exe is a Windows GUI application that doesn't write to stdout. Redirecting its output captures nothing.

Correct Way: Measure disk space before and after (as in Method 1) to determine how much space was recovered. For process monitoring, use tasklist.

Problem: cleanmgr Returns Immediately

cleanmgr /sagerun launches the cleanup process and returns immediately, it does NOT wait for cleanup to finish. If your script measures disk space immediately after the command, it will see no change because cleanup is still running in the background.

Solution: Method 1 includes a wait loop that monitors cleanmgr.exe and DismHost.exe processes, waiting for both to exit before measuring the results.

Problem: ID Conflicts with Other Software

If another script or deployment tool uses the same sageset ID, they may overwrite each other's settings.

Solution: Use a distinctive ID number. Avoid common numbers like 1, 10, or 100 if your environment has multiple cleanup scripts. Document which IDs are in use.

Best Practices and Rules

1. Pre-Configure Categories via Registry for Fleet Deployment

Method 1's registry-based approach works on any machine without manual GUI interaction. This is the correct approach for deploying to hundreds of machines via SCCM, Group Policy, or scripts.

2. Measure Space Before and After

Silent cleanup provides no visible output. The only way to know how much space was recovered is to compare free space before and after the operation.

3. Wait for Cleanup to Actually Finish

cleanmgr /sagerun returns immediately. Monitor the cleanmgr.exe process to detect actual completion.

4. Schedule During Off-Hours

Windows Update cleanup and Previous Installations removal are CPU and I/O intensive. Schedule these for nights or weekends when user impact is minimal.

5. Use Unique Sageset IDs

Document which IDs your scripts use. Avoid conflicts with other tools that may also use cleanmgr /sageset.

6. Combine with Extended Cleanup

cleanmgr doesn't cover everything. Pair it with temp file deletion, Windows Update cache clearing, and other targeted cleanup (Method 3) for comprehensive maintenance.

Conclusion

Automating Disk Cleanup via Batch provides reliable, hands-free storage maintenance. By configuring cleanup categories through the registry and using /sagerun for silent execution, you create a deployment-ready cleanup routine that works across any number of machines without manual interaction. Combining cleanmgr with extended cleanup tasks and scheduling the combined operation weekly ensures that disk space management is proactive rather than reactive.