Using PowerShell to Clear Disk Space Inside VMs

Since it’s fairly common to find VMs utilizing shared storage space that has a relatively high cost, I typically employ a number of methods to clear off unwanted files from within virtual machines. While deduplication, compression, and thin provisioning will get you along nicely, there’s still isn’t anything better than removing the unwanted files in the first place. The following script was written to comb through vCenter and perform a series of scripts within the guest operating systems that delete files from known safe locations. Please be aware that this may change from environment to environment, and you should always test removing files from your environment before pulling the trigger on a script, I can’t be held liable, blah blah blah.

The Script

Here is the script in its entirety. I believe that you will need to ensure that Windows UAC is disabled for some guest scripts to work properly or else you will get an “access denied” error.

[sourcecode language=”powershell” highlight=”2,3,4,24,25,26,27,28,29″]
### Setup
$vcenter = "fqdn.of.vcenter"
$datacenter = "Name of datacenter to search"
$folder = "Name of folder to search"

$gcreds = Get-Credential -Credential "domainusername"
$hcreds = Get-Credential -Credential "root"

### Connect
Connect-VIServer $vcenter | Out-Null
$i = 0
$vms = Get-VM -Location (Get-Datacenter $datacenter | Get-Folder $folder)

### Cleanup
function CleanSpace {

Foreach ($vm in $vms)
Write-Progress -Activity "Checking Servers" -Status "Server $i – $($vm.Name)" -PercentComplete (($i / $vms.Count)*100)

### Cleanup scripts
Write-Host -ForegroundColor:DarkGray "[INFO]: $vm Targeted for Cleanup"
Invoke-VMScript -GuestCredential $gcreds -HostCredential $hcreds -ScriptType:Bat -VM $vm -RunAsync -ScriptText "rmdir /s /q C:$Recycle.Bin" | Out-Null
Invoke-VMScript -GuestCredential $gcreds -HostCredential $hcreds -ScriptType:Bat -VM $vm -RunAsync -ScriptText "rmdir /s /q C:RECYCLER" | Out-Null
Invoke-VMScript -GuestCredential $gcreds -HostCredential $hcreds -ScriptType:Bat -VM $vm -RunAsync -ScriptText "del /S /Q C:Temp*.*" | Out-Null
Invoke-VMScript -GuestCredential $gcreds -HostCredential $hcreds -ScriptType:Bat -VM $vm -RunAsync -ScriptText "del /S /Q C:WINDOWSSoftwareDistributionDownload*.*" | Out-Null
Invoke-VMScript -GuestCredential $gcreds -HostCredential $hcreds -ScriptType:Bat -VM $vm -RunAsync -ScriptText "del C:WINDOWSsystem32wbemLogsFrameWork.log" | Out-Null
Invoke-VMScript -GuestCredential $gcreds -HostCredential $hcreds -ScriptType:Bat -VM $vm -RunAsync -ScriptText "del /S /Q C:WINDOWSPCHealthERRORREPUserDumps*.*" | Out-Null
Write-Host -ForegroundColor:DarkRed "[COMPLETE]: $vm Scripts Launched"



You’ll need to edit the code in lines 2, 3, and 4 to provide a vCenter server name and a DC/Folder to search for VMs. I used a Get-Credential cmdlet to request guest OS credentials (line 6) and ESX host credentials (line 7) to avoid having any passwords saved. Feel free to add or remove locations using the format found in line 24.

All of the Invoke-VMScript cmdlets are run async with no output to allow the fastest progression – if you find yourself troubleshooting a permissions issue, I suggest running a single line with the -RunAsync argument and Out-Null portion removed.

The actual cleanup is called in Line 34 – if you want to just test the remainder of the script without cleaning anything, comment out that line.