PowerShell System Drive Clean-up

I’ve been working through a process of cleaning and optimising the C drives on a lot of VMs recently. Over time they build up with lots of junk that, when put together with hundreds of VMs, requires a significant amount of extra primary VM storage, backup storage, and increases backup times. These files also take up space within the VM that can cause security and anti-malware updates to fail, and lead to application or logging failures. The reduced free space also leads to increased file fragmentation, which then means more IOs to and from your storage.

So the first step in my process is to run this script, which deletes various unnecessary bits and pieces from the Windows folder and user profiles, and empties recycle bins and deletes various other folders that some of my colleagues have a tendency to put onto the C drive (e.g. 5GB of SQL Server install media, which is available for them on the network).

It copes with various flavours of OS, I’ve been using it on 2003 through 2008 R2 so far. You can add paths to the array at the beginning. For paths within the Users (or Documents and Settings) folder it will search through each user profile, excluding the local administrator or any service accounts (which in my organisation all contain “svc” in the name.

I’m toying with the idea of removing the $hf_mig$ folder on 2003 now that there will be no more security updates, likewise SoftwareDistribution, but I’ve not fully looked into the implications of this yet. There’s probably lots of other places where stuff can be safely deleted from too. Another one I’ve just thought of would be *.log from the Windows folder.

The wildcards rely on the handling within the Remove-Item cmdlet, so if you’re not sure what it’ll do, it’s easy to try it manually on a test folder first.

DO NOT run this without understanding what it does, and knowing what data your applications store where, and how your users work. I AM NOT responsible if you run this and trash your server(s)! Look very carefully at the paths that I’m using and see if each one is something you feel happy with or not. That said, it hasn’t caused me any problems yet – I’ve run it on about 30 different servers so far.

Usage is:
TidyCDrive.ps1 <server name>

param([parameter(mandatory = $true)][string]$Target)

$PathsToClean = New-Object -TypeName System.Collections.ArrayList
$PathsToClean.Add('\Windows\System32\Config\SystemProfile\Local Settings\Temp\*') | Out-Null
$PathsToClean.Add('\Windows\Temp\*') | Out-Null
$PathsToClean.Add('\Windows\ie8updates') | Out-Null
$PathsToClean.Add('\Windows\ie8') | Out-Null
$PathsToClean.Add('\Windows\ie7') | Out-Null
$PathsToClean.Add('\Windows\ie7updates') | Out-Null
$PathsToClean.Add('\Windows\ServicePackFiles') | Out-Null
$PathsToClean.Add('\Windows\$NtUninstall*') | Out-Null
$PathsToClean.Add('\Windows\$NtServicePackUninstall*') | Out-Null
$PathsToClean.Add('\Windows\$950099Uinstall*') | Out-Null
$PathsToClean.Add('\Windows\$UninstallRDC$') | Out-Null
$PathsToClean.Add('\Users\xxxxx\AppData\Local\Microsoft\Windows\Temporary Internet Files') | Out-Null
$PathsToClean.Add('\Users\xxxxx\AppData\Local\Microsoft\Windows\Explorer\thumbcache*.db') | Out-Null
$PathsToClean.Add('\Users\xxxxx\AppData\Local\Microsoft\Windows\Terminal Server Client\Cache') | Out-Null
$PathsToClean.Add('\Users\xxxxx\AppData\Local\Temp\*') | Out-Null
$PathsToClean.Add('\Program Files\Veritas\Patch') | Out-Null
$PathsToClean.Add('\wuinstall') | Out-Null
$PathsToClean.Add('\$Recycle.bin\*\*') | Out-Null
$PathsToClean.Add('\Recycler\*') | Out-Null
$PathsToClean.Add('\SQL2008R2Ent') | Out-Null
$PathsToClean.Add('\SQLserver 2008 R2 SP2') | Out-Null
$PathsToClean.Add('\Security Update') | Out-Null

Write-Host ("Disk Clean & optimise for "+$Target) -ForegroundColor Gray
# record initial C drive free space
$WMIDisk = Get-WmiObject -Class Win32_LogicalDisk -ComputerName $Target -Filter "DeviceID='C:'" -ErrorAction Stop | Select-Object -Property Size,FreeSpace
[single]$CFreeSpaceBefore = $WMIDisk.FreeSpace/1GB
Write-Host ("Free space: "+$CFreeSpaceBefore)
# clean C drive based on known paths
foreach($Path in $PathsToClean){
    Write-Host ("Cleaning $Path")
    $UNCPath = ("\\"+$Target+"\C$"+$Path)
    if($UNCPath -like "*\users\xxxxx\*"){
        if(Test-Path -Path ("\\"+$Target+"\C$\Users")){
            $ProfilesFolder = ("\\"+$Target+"\C$\Users")
            $ProfilesFolder = ("\\"+$Target+"\C$\Documents and Settings")
            $UNCPath = $UNCPath.Replace("\Users\","\Documents and Settings\")
        $LocalProfiles = Get-ChildItem -Path $ProfilesFolder -Directory | Where-Object -Property Name -Like *admin* | Where-Object -Property Name -notlike "Administrator" | Where-Object -Property Name -notlike "*svc*"
        foreach($LocalProfile in $LocalProfiles){
            $UNCProfilePath = $UNCPath.Replace("xxxxx",$LocalProfile.Name)
            Write-Host $UNCProfilePath -ForegroundColor DarkGray
            Remove-Item -Path $UNCProfilePath -Recurse -Force -ErrorAction SilentlyContinue
        Write-Host $UNCPath -ForegroundColor DarkGray
        Remove-Item -Path $UNCPath -Recurse -Force -ErrorAction SilentlyContinue
# Check size of SoftwareDistribution folder isn't too large
$SD = (Get-ChildItem -Path "\\$Target\C$\Windows\SoftwareDistribution" -Recurse -Force | Measure-Object -Property Length -Sum).Sum/1MB
if($SD -gt 900){
    Write-Warning "SoftwareDistribution is a little large"
$WMIDisk = Get-WmiObject -Class Win32_LogicalDisk -ComputerName $Target -Filter "DeviceID='C:'" -ErrorAction Stop | Select-Object -Property Size,FreeSpace
[single]$CFreeSpaceAfter = $WMIDisk.FreeSpace/1GB
Write-Host ("Free space: "+$CFreeSpaceAfter)
$CFreedUpGB = $CFreeSpaceAfter - $CFreeSpaceBefore
Write-Host ("Freed up {0:N2}GB within C drive" -f $CFreedUpGB) -ForegroundColor Green
This entry was posted in Performance, PowerShell, Windows and tagged , , , , , , , , , , , , , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.