Copy the below code to your notepad and save it as .ps1 and execute the file using powershell.
#### Allow Powershell to execute scripts if it was not set before
#Set-ExecutionPolicy RemoteSigned -Scope CurrentUser
#### Check if the execution console is in Administrator previlages
$Identity = [System.Security.Principal.WindowsIdentity]::GetCurrent()
$Principal = New-Object System.Security.Principal.WindowsPrincipal $Identity
if ( $Principal.IsInRole( [System.Security.Principal.WindowsBuiltInRole]::Administrator ) -eq $false )
{
Write-Host "`nYou are not running this script with Administrator previlages. Open Powershell with Administrator previlages then run this script.`n" -ForegroundColor Cyan
exit
}
#### Heading and File Version
Write-Host "`n`t'C' DRIVE CLEANUP TOOL -v1.0 - CORE OS, MSIT.`n" -ForegroundColor Cyan
#### Variables
$LogFile = "C:\FileList_ForRemoval_From_C_Drive.txt"
$ObjShell = New-Object -ComObject Shell.Application
$WinDef = $env:ProgramData + "\Microsoft\Windows Defender"
$WERSys = $env:ALLUSERSPROFILE + "\Microsoft\Windows\WER"
#### Helper Functions
# Product Variant identifiers for Server Core editions
#define PRODUCT_DATACENTER_SERVER_CORE 0x0000000C
#define PRODUCT_STANDARD_SERVER_CORE 0x0000000D
#define PRODUCT_ENTERPRISE_SERVER_CORE 0x0000000E
#define PRODUCT_WEB_SERVER_CORE 0x0000001D
#define PRODUCT_DATACENTER_SERVER_CORE_V 0x00000027
#define PRODUCT_STANDARD_SERVER_CORE_V 0x00000028
#define PRODUCT_ENTERPRISE_SERVER_CORE_V 0x00000029
#define PRODUCT_STORAGE_EXPRESS_SERVER_CORE 0x0000002B
#define PRODUCT_STORAGE_STANDARD_SERVER_CORE 0x0000002C
#define PRODUCT_STORAGE_WORKGROUP_SERVER_CORE 0x0000002D
#define PRODUCT_STORAGE_ENTERPRISE_SERVER_CORE 0x0000002E
#define PRODUCT_STANDARD_SERVER_SOLUTIONS_CORE 0x00000035
#define PRODUCT_SOLUTION_EMBEDDEDSERVER_CORE 0x00000039
#define PRODUCT_SMALLBUSINESS_SERVER_PREMIUM_CORE 0x0000003F
# Function to check if the current OS is a Core variant or not
function Get-IsCoreOS()
{
$CoreEdition = $false
$OSSKU = Get-WmiObject Win32_OperatingSystem | Select-Object OperatingSystemSKU
switch($OSSKU.OperatingSystemSKU)
{
{ ($_ -ge 0x0C) -and ($_ -le 0x0E) } { $CoreEdition = $true}
{ ($_ -ge 0x27) -and ($_ -le 0x29) } { $CoreEdition = $true}
{ ($_ -ge 0x2B) -and ($_ -le 0x2E) } { $CoreEdition = $true}
{ ($_ -eq 0x1D) -or ($_ -eq 0x35) -or ($_ -eq 0x39) -or ($_ -eq 0x3F) } { $CoreEdition = $true}
}
$CoreEdition
}
# Calculate 'C:' Drive Free Space
$FreeSpaceOld = Get-WmiObject Win32_LogicalDisk -Filter "DeviceID = 'C:'" | Select-Object FreeSpace
# 1 # Remove User profiles that were not accessed in the last 15 days Excluding the Admin, default, public and current user profiles.
Write-Host "`n1. Removing 'User Profiles' which were not accessed in the last 15 days..." -ForegroundColor Cyan
Get-ChildItem -Path ($env:SystemDrive + "\Users") -Exclude ("Administrator", "Admin", "itsvc0", "extadministrator", "Public", "default", $env:USERNAME) | Where-Object { (New-TimeSpan $_.LastAccessTime).Days -gt 15 } | ForEach-Object `
{
$UserPath = $_.FullName
Write-Host "Deleting user profile - "$UserPath
$UserProfile = Get-WmiObject Win32_UserProfile | Where-Object { $_.LocalPath -eq $UserPath}
if ( $UserProfile -eq $null )
{
# This is just a folder without user profile
Remove-Item $UserPath -Recurse -Force -ErrorAction SilentlyContinue
}
else
{
# Delete the user profile if this is not loaded
if($UserProfile.Loaded -eq $false)
{ $UserProfile.Delete() }
}
}
# 2 # Remove Temporary Files at C:\Windows\Temp
Write-Host "`n2. Removing 'Temporary Files' at 'C:\Windows\Temp'..." -ForegroundColor Cyan
Get-ChildItem -Path ($env:windir + "\Temp") -ErrorAction SilentlyContinue | ForEach-Object { Write-Host "Deleting file - " $_.FullName ; Remove-Item $_.FullName -Recurse -Force -ErrorAction SilentlyContinue }
# 3 # Remove Following files in all user profiles
# Temporary Files at (C:\Users\USERNAME\AppData\Local\Temp
# Temporary Internet Files at (C:\Users\USERNAME\AppData\Local\Microsoft\Windows\Temporary Internet Files)
# History Files at (C:\Users\USERNAME\AppData\Local\Microsoft\Windows\History)
# WER Archive Files at (%USERPROFILE%\AppData\Local\Microsoft\Windows\WER\ReportArchive)
# WER Queue files at (%USERPROFILE%\AppData\Local\Microsoft\Windows\WER\ReportQueue)
Write-Host "`n3. Removing 'Temporary Files', 'Temporary Internet Files', 'History Files' and 'Windows Error Reporting Files' of all user profiles..." -ForegroundColor Cyan
Get-ChildItem -Path ($env:SystemDrive + "\Users") -Exclude ("Public") | ForEach-Object `
{
Get-ChildItem -Path ($_.FullName + "\AppData\Local\Temp") -ErrorAction SilentlyContinue | ForEach-Object { Write-Host "Deleting file - "$_.FullName; Remove-Item $_.FullName -Recurse -Force -ErrorAction SilentlyContinue }
Get-ChildItem -Path ($_.FullName + "\AppData\Local\Microsoft\Windows\Temporary Internet Files") -ErrorAction SilentlyContinue | ForEach-Object { Write-Host "Deleting file - "$_.FullName; Remove-Item $_.FullName -Recurse -Force -ErrorAction SilentlyContinue }
Get-ChildItem -Path ($_.FullName + "\AppData\Local\Microsoft\Windows\History") -ErrorAction SilentlyContinue | ForEach-Object { Write-Host "Deleting file - "$_.FullName; Remove-Item $_.FullName -Recurse -Force -ErrorAction SilentlyContinue }
Get-ChildItem -Path ($_.FullName + "\AppData\Local\Microsoft\Windows\WER\ReportArchive") -ErrorAction SilentlyContinue | ForEach-Object { Write-Host "Deleting file - "$_.FullName; Remove-Item $_.FullName -Recurse -Force -ErrorAction SilentlyContinue }
Get-ChildItem -Path ($_.FullName + "\AppData\Local\Microsoft\Windows\WER\ReportQueue") -ErrorAction SilentlyContinue | ForEach-Object { Write-Host "Deleting file - "$_.FullName; Remove-Item $_.FullName -Recurse -Force -ErrorAction SilentlyContinue }
}
# 4 # Remove Performance Logs Files at C:\Perflogs
Write-Host "`n4. Removing 'Performance Logs' at 'C:\Perflogs'..." -ForegroundColor Cyan
Get-ChildItem -Path ($env:SystemDrive + "\Perflogs") -ErrorAction SilentlyContinue | ForEach-Object { Write-Host "Deleting file - "$_.FullName; Remove-Item $_.FullName -Recurse -Force -ErrorAction SilentlyContinue }
# 5 # Remove remaining Temporary Files if any with *.tmp or *.tpc extensions and old chk Dsk files with .chk extension
Write-Host "`n5. Removing 'Temporary Files (*.tmp, *.tpc)' in Root, Windows and Program Files and in their sub directories..." -ForegroundColor Cyan
Get-ChildItem -Path ($env:SystemDrive + "\") | ForEach-Object `
{
if ( $_.GetType().Name -match "FileInfo" )
{
if ( ($_.Extension -eq ".tpc") -or ($_.Extension -eq ".tmp") )
{ Write-Host "Deleting file - "$_.FullName; Remove-Item $_.FullName -Recurse -Force -ErrorAction SilentlyContinue }
}
else
{
if ( ($_.Name -like "Windows") -or ($_.Name -like "Program Files*") )
{
Get-ChildItem -Path ($_.FullName) -Recurse -Include *.tmp, *.tpc -ErrorAction SilentlyContinue | ForEach-Object `
{ Write-Host "Deleting file - "$_.FullName; Remove-Item $_.FullName -Recurse -Force -ErrorAction SilentlyContinue }
}
}
}
# 6 # Remove Setup Log files at C:\Windows with setup*.old extension
Write-Host "`n6. Removing 'Old Setup log' files..." -ForegroundColor Cyan
Get-ChildItem -Path ($env:windir) -Include setup*.old -ErrorAction SilentlyContinue | ForEach-Object `
{ Write-Host "Deleting file - "$_.FullName; Remove-Item $_.FullName -Recurse -Force -ErrorAction SilentlyContinue }
# 7 # Remove Windows defender log files at C:\ProgramData\Microsoft\Windows Defender\LocalCopy and C:\ProgramData\Microsoft\Windows Defender\Support
Write-Host "`n7. Removing Windows Defender log files..." -ForegroundColor Cyan
Get-ChildItem -Path ($WinDef + "\LocalCopy"), ($WinDef + "\Support") -ErrorAction SilentlyContinue | ForEach-Object `
{ Write-Host "Deleting file - "$_.FullName; Remove-Item $_.FullName -Recurse -Force -ErrorAction SilentlyContinue }
# 8 # Remove Windows Error Reporting Files for System at %ALLUSERSPROFILE%\Microsoft\Windows\WER\ReportArchive and %ALLUSERSPROFILE%\Microsoft\Windows\WER\ReportQueue
Write-Host "`n8. Removing 'Windows Error Reporting' Files for System..." -ForegroundColor Cyan
Get-ChildItem -Path ($WERSys + "\ReportArchive"), ($WERSys + "\ReportQueue") -ErrorAction SilentlyContinue | ForEach-Object `
{ Write-Host "Deleting file - "$_.FullName; Remove-Item $_.FullName -Recurse -Force -ErrorAction SilentlyContinue }
$Number = 9
# 9 # Running Disk Cleanup Tool finally...
# Check if this Core Edition of Server. Run this tool only if it is GUI version.
$CoreOS = Get-IsCoreOS
if ($CoreOS -eq $false )
{
Write-Host "`n$Number. Finally, Running 'Disk Cleanup Tool' in user environment..." -ForegroundColor Cyan
Write-Host "`tNote: Disk Cleanup Tool opens here with all the options checked. Uncheck the checkbox against 'Memory Dump files/Debug Dump files' and 'Previous Windows Installations' and click on 'OK' to continue and delete those selected files."
# Invoke Disk Cleanup Tool
Cleanmgr /d C /LOWDISK
# Wait for 15 seconds to have cleanup manager tool launched.
Sleep 15
# Wait till Disk Cleanup Tool completes
Read-Host "`tNote: Disk Cleanup Tool launched. Wait till the tool completes its job and gets closed. Then press 'Enter' key to continue.."
$Number += 1
}
# 10 # Empty 'Recycle Bin' as Disk Cleanup Tool fails to clear it sometimes or It is not there on Core variants.
Write-Host "`n$Number. Removing files from 'Recycle Bin'..." -ForegroundColor Cyan
$ObjShell.Namespace(0xA).items() | ForEach-Object { Remove-item $_.Path -Recurse -Confirm:$false -ErrorAction SilentlyContinue }
$Number += 1
# 11 # Scan C drive for the following files and inform the user to move them from C drive.
Write-Host "`n$Number. Scanning 'C:' drive for large and other files which can be moved to another drive..." -ForegroundColor Cyan
$([char]7)
$Msg = "Following are the files that has to be moved out of the 'C:' drive as necessary. Note that the size of the file is given in KB."
Write-Host $Msg
Out-File -FilePath $LogFile -InputObject $Msg
# Dump files with *.dmp extension at C:\Windows and C:\Windows\Minidump
$Msg = "`n`nMemory Dump Files"
Write-Host $Msg -ForegroundColor Cyan
Out-File -FilePath $LogFile -Append -InputObject $Msg
$Msg = "-----------------"
Write-Host $Msg -ForegroundColor Cyan
Out-File -FilePath $LogFile -Append -InputObject $Msg
$DmpFiles = Get-ChildItem -Path ($env:windir + "\Minidump\*.*"), ($env:windir + "\*.*") -Include *.dmp -ErrorAction SilentlyContinue | Select-Object Name, FullName, @{LABEL='Size (in KB)'; EXPRESSION={$_.Length/1KB}}
Out-Host -InputObject $DmpFiles
Out-File -FilePath $LogFile -Append -InputObject $DmpFiles
# VHD files with *.vhd extension
$Msg = "`n`nVHD Files"
Write-Host $Msg -ForegroundColor Cyan
Out-File -FilePath $LogFile -Append -InputObject $Msg
$Msg = "---------"
Write-Host $Msg -ForegroundColor Cyan
Out-File -FilePath $LogFile -Append -InputObject $Msg
$VhdFiles = @()
$VhdFiles += Get-ChildItem -Path ($env:SystemDrive + "\*.*") -Include *.vhd | Select-Object Name, FullName, @{LABEL='Size (in KB)'; EXPRESSION={$_.Length/1KB}}
$VhdFiles += Get-ChildItem -Path ($env:windir), ($env:ProgramFiles), (${env:ProgramFiles(x86)}) -Recurse -Include *.vhd -ErrorAction SilentlyContinue | Select-Object Name, FullName, @{LABEL='Size (in KB)'; EXPRESSION={$_.Length/1KB}}
Out-Host -InputObject $VhdFiles
Out-File -FilePath $LogFile -Append -InputObject $VhdFiles
# ISO files with *.iso extension
$Msg = "`n`nISO Files"
Write-Host $Msg -ForegroundColor Cyan
Out-File -FilePath $LogFile -Append -InputObject $Msg
$Msg = "---------"
Write-Host $Msg -ForegroundColor Cyan
Out-File -FilePath $LogFile -Append -InputObject $Msg
$IsoFiles = @()
$IsoFiles += Get-ChildItem -Path ($env:SystemDrive + "\*.*") -Include *.iso | Select-Object Name, FullName, @{LABEL='Size (in KB)'; EXPRESSION={$_.Length/1KB}}
$IsoFiles += Get-ChildItem -Path ($env:windir), ($env:ProgramFiles), (${env:ProgramFiles(x86)}) -Recurse -Include *.iso -ErrorAction SilentlyContinue | Select-Object Name, FullName, @{LABEL='Size (in KB)'; EXPRESSION={$_.Length/1KB}}
Out-Host -InputObject $IsoFiles
Out-File -FilePath $LogFile -Append -InputObject $IsoFiles
# Old Files with *.old extension
$Msg = "`n`nOLD Files"
Write-Host $Msg -ForegroundColor Cyan
Out-File -FilePath $LogFile -Append -InputObject $Msg
$Msg = "---------"
Write-Host $Msg -ForegroundColor Cyan
Out-File -FilePath $LogFile -Append -InputObject $Msg
$OldFiles = @()
$OldFiles += Get-ChildItem -Path ($env:SystemDrive + "\*.*") -Include *.old | Select-Object Name, FullName, @{LABEL='Size (in KB)'; EXPRESSION={$_.Length/1KB}}
$OldFiles += Get-ChildItem -Path ($env:windir), ($env:ProgramFiles), (${env:ProgramFiles(x86)}) -Recurse -Include *.old -ErrorAction SilentlyContinue | Select-Object Name, FullName, @{LABEL='Size (in KB)'; EXPRESSION={$_.Length/1KB}}
Out-Host -InputObject $OldFiles
Out-File -FilePath $LogFile -Append -InputObject $OldFiles
# Backup files with *.bak and *.bup extensions
$Msg = "`n`nBACKUP Files"
Write-Host $Msg -ForegroundColor Cyan
Out-File -FilePath $LogFile -Append -InputObject $Msg
$Msg = "------------"
Write-Host $Msg -ForegroundColor Cyan
Out-File -FilePath $LogFile -Append -InputObject $Msg
$BakFiles = @()
$BakFiles += Get-ChildItem -Path ($env:SystemDrive + "\*.*") -Include *.bak, *.bup | Select-Object Name, FullName, @{LABEL='Size (in KB)'; EXPRESSION={$_.Length/1KB}}
$BakFiles += Get-ChildItem -Path ($env:windir), ($env:ProgramFiles), (${env:ProgramFiles(x86)}) -Recurse -Include *.bak, *.bup -ErrorAction SilentlyContinue | Select-Object Name, FullName, @{LABEL='Size (in KB)'; EXPRESSION={$_.Length/1KB}}
Out-Host -InputObject $BakFiles
Out-File -FilePath $LogFile -Append -InputObject $BakFiles
# Any log files with *.log and *.etl extensions including SQL setup and error log files
$Msg = "`n`nLOG Files"
Write-Host $Msg -ForegroundColor Cyan
Out-File -FilePath $LogFile -Append -InputObject $Msg
$Msg = "---------"
Write-Host $Msg -ForegroundColor Cyan
Out-File -FilePath $LogFile -Append -InputObject $Msg
$LogFiles = @()
$LogFiles += Get-ChildItem -Path ($env:SystemDrive + "\*.*") -Include *.log, *.etl | Select-Object Name, FullName, @{LABEL='Size (in KB)'; EXPRESSION={$_.Length/1KB}}
$LogFiles += Get-ChildItem -Path ($env:windir), ($env:ProgramFiles), (${env:ProgramFiles(x86)}) -Recurse -Include *.log, *.etl -ErrorAction SilentlyContinue | Select-Object Name, FullName, @{LABEL='Size (in KB)'; EXPRESSION={$_.Length/1KB}}
Out-Host -InputObject $LogFiles
Out-File -FilePath $LogFile -Append -InputObject $LogFiles
# Previous Windows Installations
$Msg = "`n`nPrevious Windows Installations"
Write-Host $Msg -ForegroundColor Cyan
Out-File -FilePath $LogFile -Append -InputObject $Msg
$Msg = "------------------------------"
Write-Host $Msg -ForegroundColor Cyan
Out-File -FilePath $LogFile -Append -InputObject $Msg
$OldWinInst = @()
$OldWinInst += Get-ChildItem -Path ($env:SystemDrive + "\") -Filter Windows*.old | Where-Object { $_.GetType().Name -match "DirectoryInfo" } -ErrorAction SilentlyContinue | Select-Object Name, FullName, @{LABEL='Size (in KB)'; EXPRESSION={$_.Length/1KB}}
Out-Host -InputObject $OldWinInst
Out-File -FilePath $LogFile -Append -InputObject $OldWinInst
Write-Host "`nAbove file details are written to the file at '$LogFile' for future reference.`n" -ForegroundColor Cyan
$Number += 1
# 12 # Calculate Free space to know the freed up space.
Write-Host "`n$Number. Calculating the free space claimed..." -ForegroundColor Cyan
$DiskSpace = Get-WmiObject Win32_LogicalDisk -Filter "DeviceID = 'C:'" | Select-Object @{LABEL="Disk Drive"; EXPRESSION={$_.DeviceID}}, @{LABEL="Size (in GB)"; EXPRESSION={$_.Size/1GB}}, @{LABEL="Free Space Before (in GB)"; EXPRESSION={$FreeSpaceOld.FreeSpace/1GB}}, @{LABEL="Free Space After (in GB)"; EXPRESSION={$_.FreeSpace/1GB}}, @{LABEL="Space Claimed (in MB)"; EXPRESSION={($_.FreeSpace - $FreeSpaceOld.FreeSpace)/1MB}}
Out-Host -InputObject $DiskSpace
#### End of script ####