Have you ever ran into a sluggish performance on a Windows machine that is being shared by many [remote] users? Chances are that each user has lots of junk files that would be saved in certain important volumes, such as C:\ drive. Thus, I’ve put together these spaghetti lines to automate maintenance of these machines.

# cleanCVolume.ps1
# Version 0.02
# This little program performs routine cleanup

## Variables Declaration ####
$directoriesToPurge=@(
    "$env:SystemDrive\Windows\Prefetch\", # $prefetchData
    "$env:SystemDrive\Windows\Logs\CBS\", # $cbs
    "$env:SystemDrive\swtools\", # $swtools
    "$env:SystemDrive\drivers\", # $drivers
    "$env:SystemDrive\swsetup\", # $swsetup
    #"$env:SystemDrive\Windows\SoftwareDistribution",
    "$env:SystemDrive\Windows\SoftwareDistribution\Download\", #$softwareDistribution
    'C:\windows\Temp',
    'C:\Temp',
    'C:\ProgramData\Microsoft\Windows\WER\ReportArchive',
    'C:\ProgramData\Microsoft\Windows\WER\ReportQueue',
    'C:\ServiceProfiles\LocalService\AppData\Local\Temp'
)
$maxConfirmations=1
$startComponentCleanup=$false
$checkSystemVolumeUtilization=$true

function cleanWindows{
    param(
        $directoriesToPurge=@(
            "$env:SystemDrive\Windows\Prefetch\", # $prefetchData
            "$env:SystemDrive\Windows\Logs\CBS\", # $cbs
            "$env:SystemDrive\swtools\", # $swtools
            "$env:SystemDrive\drivers\", # $drivers
            "$env:SystemDrive\swsetup\", # $swsetup
            "$env:SystemDrive\Windows\SoftwareDistribution\Download\", #$softwareDistribution
            'C:\windows\Temp',
            'C:\Temp',
            'C:\ProgramData\Microsoft\Windows\WER\ReportArchive',
            'C:\ProgramData\Microsoft\Windows\WER\ReportQueue',
            'C:\ServiceProfiles\LocalService\AppData\Local\Temp'
        ),
        $maxConfirmations=3,
        $startComponentCleanup=$true,
        $checkSystemVolumeUtilization=$true
    ) 

    function purgeDirectory([string[]]$paths='c:\temp',$maxConfirmations=3){     
        $unsafeLocations=@(
            'C:\',
            'C:\Program Files',
            'C:\Program Files (x86)',
            'C:\ProgramData',
            'C:\ProgramData\Microsoft',
            'C:\ProgramData\Microsoft\Windows',
            'C:\Users',
            'C:\Users\Public',
            'C:\Users\Default',
            'C:\Windows\addins',
            'C:\Windows\ADFS',
            'C:\Windows\appcompat',
            'C:\Windows\apppatch',
            'C:\Windows\AppReadiness',
            'C:\Windows\assembly',
            'C:\Windows\AutoKMS',
            'C:\Windows\bcastdvr',
            'C:\Windows\Boot',
            'C:\Windows\Branding',
            'C:\Windows\CbsTemp',
            'C:\Windows\Cluster',
            'C:\Windows\Containers',
            'C:\Windows\CSC',
            'C:\Windows\Cursors',
            'C:\Windows\debug',
            'C:\Windows\diagnostics',
            'C:\Windows\DiagTrack',
            'C:\Windows\DigitalLocker',
            'C:\Windows\Downloaded Program Files',
            'C:\Windows\en-US',
            'C:\Windows\Fonts',
            'C:\Windows\GameBarPresenceWriter',
            'C:\Windows\Globalization',
            'C:\Windows\Help',
            'C:\Windows\IdentityCRL',
            'C:\Windows\IME',
            'C:\Windows\ImmersiveControlPanel',
            'C:\Windows\INF',
            'C:\Windows\InputMethod',
            'C:\Windows\L2Schemas',
            'C:\Windows\LiveKernelReports',
            'C:\Windows\Logs',
            'C:\Windows\Media',
            'C:\Windows\Microsoft.NET',
            'C:\Windows\Migration',
            'C:\Windows\Minidump',
            'C:\Windows\ModemLogs',
            'C:\Windows\OCR',
            'C:\Windows\Offline Web Pages',
            'C:\Windows\Panther',
            'C:\Windows\Performance',
            'C:\Windows\PLA',
            'C:\Windows\PolicyDefinitions',
            'C:\Windows\PrintDialog',
            'C:\Windows\Provisioning',
            'C:\Windows\Registration',
            'C:\Windows\RemotePackages',
            'C:\Windows\rescache',
            'C:\Windows\Resources',
            'C:\Windows\SchCache',
            'C:\Windows\schemas',
            'C:\Windows\security',
            'C:\Windows\ServiceProfiles',
            'C:\Windows\ServiceState',
            'C:\Windows\servicing',
            'C:\Windows\Setup',
            'C:\Windows\ShellComponents',
            'C:\Windows\ShellExperiences',
            'C:\Windows\SHELLNEW',
            'C:\Windows\SKB',
            'C:\Windows\Speech',
            'C:\Windows\Speech_OneCore',
            'C:\Windows\System',
            'C:\Windows\System32',
            'C:\Windows\SystemApps',
            'C:\Windows\SystemResources',
            'C:\Windows\SystemTemp',
            'C:\Windows\SysWOW64',
            'C:\Windows\TAPI',
            'C:\Windows\Tasks',
            'C:\Windows\TextInput',
            'C:\Windows\tracing',
            'C:\Windows\twain_32',
            'C:\Windows\Vss',
            'C:\Windows\WaaS',
            'C:\Windows\Web',
            'C:\Windows\WinSxS'
        )
        
        $results=[hashtable]@{}
        $emptyDirectory="C:\emptyDirectory"
        foreach($path in $paths){
            if($path -in $unsafeLocations){
                write-warning "'$path' is an unsafe location to purge! This iteration shall be skipped"
                $results+=[hashtable]@{$path='Not purged'}
                #continue
            }else{
                # write-host "Granting Administrators full access to $path..."
                # try{
                #     # $null=takeown /F $path /A /R /D Y
                #     $null=icacls $path /Grant Administrators:F /inheritance:e /T
                # }catch{
                #     write-warning $_
                #     continue
                # }                
                $null=md -Force $emptyDirectory
                Remove-Item "$emptyDirectory`\*" -force -recurse -ErrorAction Continue
                $validPath=if(test-path $path -EA SilentlyContinue){$true}else{$false}
                if(--$maxConfirmations -ge 0){
                    $confirmed=confirmation "This will delete all files and folders from $path"
                    if ($confirmed -and $validPath){
                        write-host "Now purging ALL files and folders inside $path..." -foregroundcolor yellow
                        $null=robocopy $emptyDirectory $path /mir /R:0 /W:0 /NP
                        $results+=[hashtable]@{$path='Purged'}
                        # rmdir -Force $path
                    }else{
                        write-host "Purging has been cancelled for $path and any/all subsequent paths"
                        $results+=[hashtable]@{$path='NOT purged'}
                        break
                    }
                }else{
                    write-host "Now purging ALL files and folders inside $path..." -foregroundcolor yellow
                    $null=robocopy $emptyDirectory $path /mir /R:0 /W:0 /NP
                    $results+=[hashtable]@{$path='Purged'}
                }
            }            
        }
        return $results
    }
    
    function getUserProfiles{
        $userTempDirectories=@()
        $profiles=(get-childitem 'C:\users' -Directory -EA Ignore).Name
        if($profiles){
            Foreach($profile in $profiles){            
                $tempPath = "C:\Users\$profile\AppData\Local\Temp"
                $downloadPath = "C:\Users\$profile\Downloads"
                $userTempDirectories+=$tempPath
                $userTempDirectories+=$downloadPath
                # purgeDirectory $tempPath
                # Write-host "$tempPath cleared."
                # purgeDirectory $downloadPath
                # Write-host "$downloadPath cleared."
            }
        }else{
            write-warning "There are no user profiles detected."
        }
        return $userTempDirectories
    }
    
    function confirmation($content,$testValue="I confirm",$maxAttempts=3){
        $confirmed=$false;
        $attempts=0;        
        $content|write-host
        write-host "Please review this content for accuracy.`r`n"
        while ($attempts -le $maxAttempts){
            if($attempts++ -ge $maxAttempts){
                write-host "A maximum number of attempts have reached. No confirmations received!`r`n"
                break;
                }
            $userInput = Read-Host -Prompt "Please type in this value => $testValue <= to confirm. Input CANCEL to skip this item.";
            if ($userInput.ToLower() -eq $testValue.ToLower()){
                $confirmed=$true;
                write-host "Confirmed!`r`n";
                break;                
            }elseif($userInput -like 'cancel'){
                write-host 'Cancel command received.'
                $confirmed=$false
                break
            }else{
                cls;
                $content|write-host
                write-host "Attempt number $attempts of $maxAttempts`: $userInput does not match $testValue. Try again or Input CANCEL to skip this item`r`n"
                }
            }
        return $confirmed;
    }
    # $directoriesToPurge=$directoriesToPurge.ToArray()
    $directoriesToPurge+=$(getUserProfiles)
    purgeDirectory $directoriesToPurge $maxConfirmations    
    if($startComponentCleanup){
        write-host "Now clearing all superseded versions of every component in the component store...."
        write-host "This also removes any backup components needed for uninstallation of service packs already installed"
        Dism.exe /online /Cleanup-Image /startcomponentcleanup /resetbase
    }
    if($checkSystemVolumeUtilization){
        $disk = Get-WmiObject Win32_LogicalDisk -Filter "DeviceID='$env:SystemDrive'"|Select-Object Size,FreeSpace
        $capacity=[math]::round($disk.Size/1GB,2)
        $freeSpace=[math]::round($disk.FreeSpace/1GB,2)
        $utilizedPercent=[math]::round(($disk.Size-$disk.FreeSpace)/$disk.Size*100,2)
        write-host "$freeSpace`GB of $capacity`GB is available. Utilization: $utilizedPercent%"
    }
}

cleanWindows $directoriesToPurge $maxConfirmations $startComponentCleanup

How to check system volumes on a list of remote Windows machines

# Check a list of remote Windows machines
$computernames=@'
windows1
windows2
'@
$computernames=@($computernames -split "`n")|%{$_.Trim()}

# Generate a list of disk utilization on Remote servers
foreach ($computername in $computernames){
    invoke-command -computername $computername -scriptblock{
        $disk=Get-WmiObject Win32_LogicalDisk -Filter "DeviceID='$env:SystemDrive'"|Select-Object Size,FreeSpace
        $capacity=[math]::round($disk.Size/1GB,2)
        $freeSpace=[math]::round($disk.FreeSpace/1GB,2)
        $utilizedPercent=[math]::round(($disk.Size-$disk.FreeSpace)/$disk.Size*100,2)
        return [pscustomobject]@{
            computerName=$env:computername
            freeSpaceGb=$freeSpace
            capacityGb=$capacity
            utilizationPercent=$utilizedPercent
        }
    } |select-object -property * -excludeproperty PSComputerName,RunspaceId
}
# cleanCVolume.ps1
# Version 0.01

## Variables Declaration ####
$directoriesToPurge=@(
    "$env:SystemDrive\Windows\Prefetch\", # $prefetchData
    "$env:SystemDrive\Windows\Logs\CBS\", # $cbs
    "$env:SystemDrive\swtools\", # $swtools
    "$env:SystemDrive\drivers\", # $drivers
    "$env:SystemDrive\swsetup\", # $swsetup
    "$env:SystemDrive\Windows\SoftwareDistribution\Download\", #$softwareDistribution
    'C:\windows\Temp',
    'C:\Temp',
    'C:\ProgramData\Microsoft\Windows\WER\ReportArchive',
    'C:\ProgramData\Microsoft\Windows\WER\ReportQueue',
    'C:\ServiceProfiles\LocalService\AppData\Local\Temp'
)


function purgeDirectory($path='c:\temp'){     
    function confirmation($content,$testValue="I confirm",$maxAttempts=3){
            $confirmed=$false;
            $attempts=0;        
            $content|write-host
            write-host "Please review this content for accuracy.`r`n"
            while ($attempts -le $maxAttempts){
                if($attempts++ -ge $maxAttempts){
                    write-host "A maximum number of attempts have reached. No confirmations received!`r`n"
                    break;
                    }
                $userInput = Read-Host -Prompt "Please type in this value => $testValue <= to confirm. Input CANCEL to skip this item.";
                if ($userInput.ToLower() -eq $testValue.ToLower()){
                    $confirmed=$true;
                    write-host "Confirmed!`r`n";
                    break;                
                }elseif($userInput -like 'cancel'){
                    write-host 'Cancel command received.'
                    $confirmed=$false
                    break
                }else{
                    cls;
                    $content|write-host
                    write-host "Attempt number $attempts of $maxAttempts`: $userInput does not match $testValue. Try again or Input CANCEL to skip this item`r`n"
                    }
                }
            return $confirmed;
        }
    write-host "Granting Administrators full access to $path..."
    try{
        # $null=takeown /F $path /A /R /D Y
        $null=icacls $path /Grant Administrators:F /inheritance:e /T
    }catch{
        write-warning $_
        continue
    }
    $emptyDirectory="C:\emptyDirectory"
    md -Force $emptyDirectory
    Remove-Item "$emptyDirectory`\*" -force -recurse -ErrorAction Continue
    $confirmed=confirmation "This will delete all files and folders from $path"
    if ($confirmed){
        write-host "Now purging ALL files and folders inside $path..." -foregroundcolor yellow
        $null=robocopy $emptyDirectory $path /mir /R:0 /W:0 /NP
        # rmdir -Force $path
    }else{
        write-host "Purging has been cancelled for $path"
        }
}
function cleanUserProfiles{
    $profiles=(get-childitem c:\users -Directory -EA Ignore).Name
    if($profiles){
        Foreach($profile in $profiles){            
            $tempPath = "C:\Users\$profile\AppData\Local\Temp"
            $downloadPath = "C:\Users\$profile\Downloads"
            purgeDirectory $tempPath
            Write-host "$tempPath cleared."
            purgeDirectory $downloadPath
            Write-host "$downloadPath cleared."
        }
    }
}

function cleanWindows{
    foreach($directoryToPurge in $directoriesToPurge){
        purgeDirectory $directoryToPurge
    }
    write-host "Clearing all superseded versions of every component in the component store...."
    # This also removes any backup components needed for uninstallation of service packs already installed
    Dism.exe /online /Cleanup-Image /startcomponentcleanup /resetbase
}

cleanUserProfiles
cleanWindows