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
Categories: