Version 2:
# cleanupWindows.ps1
# Version 0.0.2
################################## Excuting Program as an Administrator ####################################
# Run this function ad-hoc to relaunch as Admin prior to going through the next commands
Function elevate{
# Get the ID and security principal of the current user account
$myWindowsID=[System.Security.Principal.WindowsIdentity]::GetCurrent()
$myWindowsPrincipal=new-object System.Security.Principal.WindowsPrincipal($myWindowsID)
# Get the security principal for the Administrator role
$adminRole=[System.Security.Principal.WindowsBuiltInRole]::Administrator
# Check to see if we are currently running "as Administrator"
if ($myWindowsPrincipal.IsInRole($adminRole)){
# We are running "as Administrator" - so change the title and background color to indicate this
$Host.UI.RawUI.WindowTitle = $myInvocation.MyCommand.Definition + "(Elevated)"
$Host.UI.RawUI.BackgroundColor = "Black"
clear-host
}else{
# Relaunch as administrator
start-process powershell -verb runas
# Exit from the current, unelevated, process
exit
}
Write-Host -NoNewLine "Running as Administrator..."
}
# Get the ID and security principal of the current user account
$myWindowsID=[System.Security.Principal.WindowsIdentity]::GetCurrent()
$myWindowsPrincipal=new-object System.Security.Principal.WindowsPrincipal($myWindowsID)
# Get the security principal for the Administrator role
$adminRole=[System.Security.Principal.WindowsBuiltInRole]::Administrator
# Check to see if we are currently running "as Administrator"
if ($myWindowsPrincipal.IsInRole($adminRole)){
# We are running "as Administrator" - so change the title and background color to indicate this
$Host.UI.RawUI.WindowTitle = $myInvocation.MyCommand.Definition + "(Elevated)"
$Host.UI.RawUI.BackgroundColor = "Black"
clear-host
}else{
# We are not running "as Administrator" - so relaunch as administrator
# Create a new process object that starts PowerShell
$newProcess = new-object System.Diagnostics.ProcessStartInfo "PowerShell";
# Specify the current script path and name as a parameter
$newProcess.Arguments = $myInvocation.MyCommand.Definition;
# Indicate that the process should be elevated
$newProcess.Verb = "runas";
# Start the new process
[System.Diagnostics.Process]::Start($newProcess);
# Exit from the current, unelevated, process
exit
}
Write-Host -NoNewLine "Running as Administrator..."
################################## Excuting Program as an Administrator ####################################
function cleanupWindows($removeBloatware=$true){
## Variables Declaration ####
$prefetchData="$env:SystemDrive\Windows\Prefetch\*"
$cbs="$env:SystemDrive\Windows\Logs\CBS\*"
$swtools="$env:SystemDrive\swtools\*"
$drivers="$env:SystemDrive\drivers\*"
$swsetup="$env:SystemDrive\swsetup\*"
$softwareDistribution="$env:SystemDrive\Windows\SoftwareDistribution\Download\*"
function cleanup{
param([string[]]$directory)
foreach ($x in $directory){
if ($x.Substring($x.Length - 2) -ne "\*"){
if($x.Substring($x.Length - 1) -ne "\"){$x+="\*"}else{$x+="*"}
}
Remove-Item -Path $x -Force -Recurse -ea Ignore -Confirm:$false
}
}
function runDiskCleanup{
$ErrorActionPreference = 'Stop'
Try{
Start-Process -FilePath Cleanmgr -ArgumentList '/sagerun:1' -Wait
write-host "Windows Disk Cleanup has been successful." -ForegroundColor Green
return $true
}
Catch{
write-warning $_
return $False
}
}
function runDism{
$ErrorActionPreference = 'Stop'
Try{
$dismResult = dism.exe /online /cleanup-Image /spsuperseded
If($dismResult -match 'The operation completed successfully\.$'){
Write-Host "DISM Completed Successfully." -ForegroundColor Green
}Else{
Write-Host "DISM is unable to clean old ServicePack Files." -ForegroundColor Red
}
return $dismResult
}
Catch [System.Exception]{
$ErrorActionPreference = 'SilentlyContinue'
return $False
}
}
function runIisCleanup{
param(
$deleteLogsOlderThanDays=30
)
$iisExists=.{Try{
Import-Module WebAdministration -ErrorAction Stop
return $True
}Catch{
return $False
}}
if($iisExists){
$iisLogPaths = .{
$null=Import-Module WebAdministration
Add-PSSnapin WebAdministration -ErrorAction SilentlyContinue
Import-Module WebAdministration -ErrorAction SilentlyContinue
$iisLogs = @()
foreach($website in $(get-website)){
$logDirectory="$($website.logFile.directory)\w3svc$($website.id)".replace("%SystemDrive%",$env:SystemDrive)
$logInfo = [pscustomobject] @{
sitename = $website.name
logDirectory = $logDirectory
}
$iisLogs += $logInfo
}
return $iisLogs
}
If($iisLogPaths){
Foreach($item in $iisLogPaths){
Write-host "Checking Website : $($item.sitename)"
$oldLogs=.{
$ErrorActionPreference='stop'
Try{
$logFiles=Get-ChildItem $item.logDirectory -Recurse -File *.log -EA Ignore
$expiredLogs=$logFiles | where-object LastWriteTime -le ((get-date).AddDays(-$deleteLogsOlderThanDays))
return $expiredLogs.FullName
}Catch{
return $Null
}
}
If ($($oldLogs | Measure-Object).count -gt 0){
ForEach ($file in $oldLogs){
remove-item $file -force
write-host "Purged: $file"
}
}else{
Write-Host "No IIS Log Files Older than $deleteLogsOlderThanDays days for $($item.sitename)." -ForegroundColor Green
}
}
Write-Host "IIS Log files purging older than $deleteLogsOlderThanDays days have completed!" -ForegroundColor Green
}
}else{
write-host "IIS is not detected on $env:computername"
}
}
function cleanUserProfiles{
$profiles=(get-childitem c:\users -Directory -EA Ignore).Name
if($profiles){
Foreach($profile in $profiles){
Write-host "Processing profile: $profile"
$tempPath = "C:\Users\$profile\AppData\Local\Temp"
$downloadPath = "C:\Users\$profile\Downloads"
cleanup $tempPath
cleanup $downloadPath
}
}
}
Function clearRecycleBinLegacy($retentionDays=0){
# This function doesn't work on Windows 10
Try{
$shell = New-Object -ComObject Shell.Application
$recycleBin = $shell.NameSpace(0xa)
foreach($item in $recycleBin.Items()){
$deletedDate = $recycleBin.GetDetailsOf($item,2) -replace "\u200f|\u200e","" #Invisible Unicode Characters
$deletedDateTime = Get-Date $deletedDate
[Int]$deletedDays = (New-TimeSpan -Start $deletedDateTime -End $(Get-Date)).Days
write-host $deletedDate
If($deletedDays -ge $retentionDays){
Remove-Item -Path $item.Path -Confirm:$false -Force -Recurse
}
}
return $true
}Catch {
write-warning $_
return $false
}
}
function removeBloatware{
$osType=switch ((Get-CimInstance -ClassName Win32_OperatingSystem).ProductType){
1 {'client'} # ClientOs
2 {'domaincontroller'} #ServerOs
3 {'memberserver'}
}
$windowsVersion=[System.Environment]::OSVersion.Version
if($osType -eq 'client' -and $windowsVersion -ge [version]'10.0'){
write-host 'Removing bloatware...'
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$bloatwareRemovalDownload="https://github.com/Sycnex/Windows10Debloater/archive/master.zip"
$bloatwareRemovalDestination="C:\Temp\Windows10Debloater-master.zip"
(New-Object System.Net.WebClient).DownloadFile($bloatwareRemovalDownload, $bloatwareRemovalDestination)
$destination="C:\Temp"
expand-archive -path $bloatwareRemovalDestination -DestinationPath $destination
PowerShell.exe -executionpolicy bypass -File C:\Temp\Windows10Debloater-master\Windows10Debloater.ps1 -Confirm:$False
}else{
write-host "Windows $windowsVersion is a $osType. Hence, this bloatware removal routine doesn't apply."
}
}
write-host "Delete files in Temp directories..."
cleanup 'C:\windows\Temp','C:\Temp'
cleanup 'C:\ProgramData\Microsoft\Windows\WER\ReportArchive'
cleanup 'C:\ProgramData\Microsoft\Windows\WER\ReportQueue'
cleanup 'C:\ServiceProfiles\LocalService\AppData\Local\Temp'
cleanup $softwareDistribution
write-Host "Clean prefetch data..."
cleanup $prefetchData
write-Host "Clean CBS logs..."
$null=stop-service wuauserv
cleanup $cbs
start-service wuauserv
write-Host "Clean swtools data..."
cleanup $swtools
write-Host "Clean drivers data..."
cleanup $drivers
write-Host "Clean swsetup data..."
cleanup $swsetup
write-Host "Clean softwareDistribution data..."
cleanup $softwareDistribution
cleanUserProfiles
runDiskCleanup
runDism
runIisCleanup
write-host "Disabling Automatic Startup Repair..."
$null=cmd.exe /c "bcdedit /set {default} recoveryenabled No"
$null=cmd.exe /c "bcdedit /set {default} bootstatuspolicy ignoreallfailures"
write-host 'Turning off hibernation to remove disk reservations for that purpose'
$null=powercfg /setactive SCHEME_MIN
$null=powercfg /hibernate off
$windowsVersion=[System.Environment]::OSVersion.Version
if($windowsVersion -lt [version]'10.0'){
clearRecycleBin
}else{
write-host 'Disabling Windows Media (a vector of attack surface from malware)'
Disable-WindowsOptionalFeature -FeatureName "WindowsMediaPlayer" -Online
write-host 'Disabling XPS...'
Disable-WindowsOptionalFeature -Online -FeatureName "Printing-XPSServices-Features"
write-host 'Removing Workfolder Client'
Disable-WindowsOptionalFeature -Online -FeatureName "WorkFolders-Client"
write-host 'Removing Windows Store'
Get-AppxPackage -AllUsers | Where-Object {$_.Name -like "Microsoft.WindowsStore*"} | remove-appxpackage
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
write-Host "Emptying Recycle Bin." -ForegroundColor Yellow
Clear-RecycleBin -Force # PoweerShell 5
write-host "Prune Event Logs..."
$null=wevtutil el | Foreach-Object {wevtutil cl "$_"}
write-host "Performing Disk Cleanup..."
(Get-Volume).DriveLetter|ForEach-Object{cleanmgr /d $_ /VeryLowDisk}
write-host 'Disabling the annoying Windows Update notifications...'
$system32="$env:windir\System32"
$annoyingNotifications="$system32\musnotification.exe","$system32\musnotificationux.exe"
$denyExecute= New-Object System.Security.AccessControl.FileSystemAccessRule("Everyone","Execute","Deny")
$annoyingNotifications|ForEach-Object{
$acl = Get-ACL $_
$acl.AddAccessRule($denyExecute)
Set-Acl $_ $acl
}
}
if($removeBloatware){removeBloatware}
$volumes = gwmi -Class win32_volume -Filter "DriveType!=5" -ea stop| ?{$_.DriveLetter -ne $isnull}|`
Select-object @{Name="Letter";Expression={$_.DriveLetter}},`
@{Name="Label";Expression={$_.Label}},`
@{Name="Capacity";Expression={"{0:N2} GiB" -f ($_.Capacity/1073741824)}},`
@{Name = "Available"; Expression = {"{0:N2} GiB" -f ($_.FreeSpace/1073741824)}},`
@{Name = "Utilization"; Expression = {"{0:N2} %" -f ((($_.Capacity-$_.FreeSpace) / $_.Capacity)*100)}}`
| sort -property Letter
write-host "Current storage stats:`r`n$volumes"
return $volumes
}
cleanupWindows
Version 1:
# Windows-Cleanup-v0.01.ps1
################################## Excuting Program as an Administrator ####################################
# Run this function ad-hoc to relaunch as Admin prior to going through the next commands
Function elevate{
# Get the ID and security principal of the current user account
$myWindowsID=[System.Security.Principal.WindowsIdentity]::GetCurrent()
$myWindowsPrincipal=new-object System.Security.Principal.WindowsPrincipal($myWindowsID)
# Get the security principal for the Administrator role
$adminRole=[System.Security.Principal.WindowsBuiltInRole]::Administrator
# Check to see if we are currently running "as Administrator"
if ($myWindowsPrincipal.IsInRole($adminRole))
{
# We are running "as Administrator" - so change the title and background color to indicate this
$Host.UI.RawUI.WindowTitle = $myInvocation.MyCommand.Definition + "(Elevated)"
$Host.UI.RawUI.BackgroundColor = "Black"
clear-host
}
else
{
# Relaunch as administrator
start-process powershell -verb runas
# Exit from the current, unelevated, process
exit
}
Write-Host -NoNewLine "Running as Administrator..."
}
# Get the ID and security principal of the current user account
$myWindowsID=[System.Security.Principal.WindowsIdentity]::GetCurrent()
$myWindowsPrincipal=new-object System.Security.Principal.WindowsPrincipal($myWindowsID)
# Get the security principal for the Administrator role
$adminRole=[System.Security.Principal.WindowsBuiltInRole]::Administrator
# Check to see if we are currently running "as Administrator"
if ($myWindowsPrincipal.IsInRole($adminRole))
{
# We are running "as Administrator" - so change the title and background color to indicate this
$Host.UI.RawUI.WindowTitle = $myInvocation.MyCommand.Definition + "(Elevated)"
$Host.UI.RawUI.BackgroundColor = "Black"
clear-host
}
else
{
# We are not running "as Administrator" - so relaunch as administrator
# Create a new process object that starts PowerShell
$newProcess = new-object System.Diagnostics.ProcessStartInfo "PowerShell";
# Specify the current script path and name as a parameter
$newProcess.Arguments = $myInvocation.MyCommand.Definition;
# Indicate that the process should be elevated
$newProcess.Verb = "runas";
# Start the new process
[System.Diagnostics.Process]::Start($newProcess);
# Exit from the current, unelevated, process
exit
}
Write-Host -NoNewLine "Running as Administrator..."
################################## Excuting Program as an Administrator ####################################
function cleanupWindows{
## Variables Declaration ####
$userAppDataTempFolders = (get-ChildItem "env:\TEMP").Value
$windowsTemp = "$env:SystemDrive\Windows\Temp\*";
$homeFolders=(dir "$env:SystemDrive\Users").FullName
$userDownloadFolders=$homeFolders|%{"$env:SystemDrive\$_\Downloads\*"}
$prefetchData="$env:SystemDrive\Windows\Prefetch\*"
$cbs="$env:SystemDrive\Windows\Logs\CBS\*"
$swtools="$env:SystemDrive\swtools\*"
$drivers="$env:SystemDrive\drivers\*"
$swsetup="$env:SystemDrive\swsetup\*"
$softwareDistribution="$env:SystemDrive\Windows\SoftwareDistribution\Download\*"
$recyclebin = (New-Object -ComObject Shell.Application).Namespace(0xA)
# Performing cleanup tasks
function cleanup{
param($item)
if ($item.Substring($item.Length - 2) -ne "\*"){
if($item.Substring($item.Length - 1) -ne "\"){$item+="\*"}else{$item+="*"}
}
Remove-Item $item -Force -Recurse -ea SilentlyContinue -Confirm:$false
}
$myWindowsID=[System.Security.Principal.WindowsIdentity]::GetCurrent()
$myWindowsPrincipal=new-object System.Security.Principal.WindowsPrincipal($myWindowsID)
# Get the security principal for the Administrator role
$adminRole=[System.Security.Principal.WindowsBuiltInRole]::Administrator
if ($myWindowsPrincipal.IsInRole($adminRole)){
"Clear Windows Update Cache..."
#Dism.exe /online /Cleanup-Image /spsuperseded #remove any backup components needed for uninstallation of the service pack
Dism.exe /online /Cleanup-Image /startcomponentcleanup /resetbase #removes all superseded versions of every component in the component store.
write-Host "Delete files in Temp directories..."
$userAppDataTempFolders|%{cleanup $_}
cleanup $windowsTemp
cleanup "C:\Temp"
write-Host "Cleanup Downloads..."
$userDownloadFolders|%{cleanup $_}
write-Host "Clean prefetch data..."
cleanup $prefetchData
write-Host "Clean CBS logs..."
$windowsUpdateStopped=net stop wuauserv
if ($windowsUpdateStopped){
cleanup $cbs
net start wuauserv
}
write-Host "Clean swtools data..."
cleanup $swtools
write-Host "Clean drivers data..."
cleanup $drivers
write-Host "Clean swsetup data..."
cleanup $swsetup
write-Host "Clean softwareDistribution data..."
cleanup $softwareDistribution
write-Host "Emptying Recycle Bin." -ForegroundColor Yellow
$Recyclebin.items() | %{cleanup $_.path}
"Performing Disk Cleanup..."
$HKLM = [UInt32] "0x80000002"
$strKeyPath = "SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches"
$strValueName = "StateFlags0065"
$subkeys = gci -Path HKLM:\$strKeyPath -Name
ForEach ($subkey in $subkeys) {
New-ItemProperty -Path HKLM:\$strKeyPath\$subkey -Name $strValueName -PropertyType DWord -Value 2 -ErrorAction SilentlyContinue| Out-Null
Start-Process cleanmgr -ArgumentList "/sagerun:65" -Wait -NoNewWindow -ErrorAction SilentlyContinue -WarningAction SilentlyContinue
}
ForEach ($subkey in $subkeys) {
Remove-ItemProperty -Path HKLM:\$strKeyPath\$subkey -Name $strValueName | Out-Null
}
#"Prune Event Logs..."
#wevtutil el | Foreach-Object {wevtutil cl "$_"}
write-Host "**Clean Up completed**"
}else{
write-host "Need to run 'elevate' function to relaunch as Administrator prior to retrying 'cleanupWindows'..."
}
}
cleanupWindows;
# Verify volumes utilization after performing cleanup routines
$volumes = (gwmi -Class win32_volume -Filter "DriveType!=5" -ea stop| ?{$_.DriveLetter -ne $isnull}|`
Select-object @{Name="Letter";Expression={$_.DriveLetter}},`
@{Name="Label";Expression={$_.Label}},`
@{Name="Capacity";Expression={"{0:N2} GiB" -f ($_.Capacity/1073741824)}},`
@{Name = "Available"; Expression = {"{0:N2} GiB" -f ($_.FreeSpace/1073741824)}},`
@{Name = "Utilization"; Expression = {"{0:N2} %" -f ((($_.Capacity-$_.FreeSpace) / $_.Capacity)*100)}}`
| ft -autosize | Out-String).Trim()
write-host $volumes
Error:
Clear Windows Update Cache...
Deployment Image Servicing and Management tool
Version: 6.3.9600.19408
Image Version: 6.3.9600.19397
[==========================100.0%==========================]
Error: 14098
The component store has been corrupted.
The DISM log file can be found at C:\Windows\Logs\DISM\dism.log
Delete files in Temp directories...
Cleanup Downloads...
Clean prefetch data...
Clean CBS logs...
The Windows Update service is starting.
The Windows Update service was started successfully.
Resolve:
function resetWindowsUpdate{
# Source: https://learn.microsoft.com/en-us/troubleshoot/windows-client/installing-updates-features-roles/additional-resources-for-windows-update
net stop wuauserv /y
net stop cryptSvc /y
net stop bits /y
net stop msiserver /y
Ren "$env:systemroot\SoftwareDistribution" SoftwareDistribution.old
Ren "$env:systemroot\System32\catroot2" Catroot2.old
netsh winsock reset
net start wuauserv
net start cryptSvc
net start bits
bitsadmin.exe /reset /allusers
net start msiserver
DISM.exe /Online /Cleanup-image /Restorehealth
}
resetWindowsUpdate
Categories: