Загрузка данных
$ErrorActionPreference = "Continue"
$TimeStamp = Get-Date -Format "yyyyMMdd_HHmmss"
$Log = "C:\Disk_C_UserCache_Cleanup_$TimeStamp.log"
function Write-Log {
param(
[string]$Text
)
$Line = "{0} {1}" -f `
(Get-Date -Format "yyyy-MM-dd HH:mm:ss"),
$Text
Write-Host $Line
$Line |
Out-File `
-FilePath $Log `
-Append `
-Encoding UTF8
}
function Get-CDriveInfo {
$Drive = Get-WmiObject `
-Class Win32_LogicalDisk `
-Filter "DeviceID='C:'"
[pscustomobject]@{
SizeGB = [math]::Round(
$Drive.Size / 1GB,
2
)
UsedGB = [math]::Round(
($Drive.Size - $Drive.FreeSpace) / 1GB,
2
)
FreeGB = [math]::Round(
$Drive.FreeSpace / 1GB,
2
)
FreePct = [math]::Round(
($Drive.FreeSpace / $Drive.Size) * 100,
1
)
}
}
function Format-Size {
param(
[long]$Bytes
)
if ($Bytes -ge 1GB) {
return "{0:N2} GB" -f ($Bytes / 1GB)
}
if ($Bytes -ge 1MB) {
return "{0:N2} MB" -f ($Bytes / 1MB)
}
if ($Bytes -ge 1KB) {
return "{0:N2} KB" -f ($Bytes / 1KB)
}
return "$Bytes B"
}
function Get-PathSize {
param(
[string]$Path
)
if (-not (Test-Path -LiteralPath $Path)) {
return 0L
}
try {
$Item = Get-Item `
-LiteralPath $Path `
-Force `
-ErrorAction Stop
if (-not $Item.PSIsContainer) {
return [long]$Item.Length
}
$Measure = Get-ChildItem `
-LiteralPath $Path `
-File `
-Force `
-Recurse `
-ErrorAction SilentlyContinue |
Measure-Object `
-Property Length `
-Sum
if ($Measure.Sum) {
return [long]$Measure.Sum
}
}
catch {
}
return 0L
}
function Get-BlockingProcesses {
param(
[string]$User,
[string[]]$ProcessNames
)
$Result = $Script:OwnedProcesses |
Where-Object {
$_.User -ieq $User -and
$ProcessNames -icontains $_.Name
}
return @($Result)
}
function Clear-CacheDirectory {
param(
[string]$User,
[string]$Category,
[string]$Path,
[string[]]$BlockingProcesses
)
if (-not (Test-Path -LiteralPath $Path)) {
Write-Log (
"Отсутствует: {0}" -f $Path
)
return
}
$SizeBefore = Get-PathSize -Path $Path
if ($SizeBefore -eq 0) {
Write-Log (
"Пустой каталог: {0}" -f $Path
)
return
}
$Blockers = Get-BlockingProcesses `
-User $User `
-ProcessNames $BlockingProcesses
if ($Blockers.Count -gt 0) {
$Names = (
$Blockers |
Select-Object -ExpandProperty Name -Unique
) -join ", "
Write-Log (
"ПРОПУЩЕНО: {0}; путь: {1}; у пользователя {2} работают процессы: {3}" -f `
$Category,
$Path,
$User,
$Names
)
return
}
Write-Log (
"Очистка: {0}; путь: {1}; размер: {2}" -f `
$Category,
$Path,
(Format-Size $SizeBefore)
)
$RemovedBytes = 0L
$FailedCount = 0
$Items = Get-ChildItem `
-LiteralPath $Path `
-Force `
-ErrorAction SilentlyContinue
foreach ($Item in $Items) {
$ItemSize = Get-PathSize -Path $Item.FullName
try {
Remove-Item `
-LiteralPath $Item.FullName `
-Recurse `
-Force `
-ErrorAction Stop
$RemovedBytes += $ItemSize
}
catch {
$FailedCount++
Write-Log (
"Не удалось удалить: {0}; ошибка: {1}" -f `
$Item.FullName,
$_.Exception.Message
)
}
}
$SizeAfter = Get-PathSize -Path $Path
$ActualDirectoryFreed = $SizeBefore - $SizeAfter
if ($ActualDirectoryFreed -lt 0) {
$ActualDirectoryFreed = 0
}
$Script:EstimatedFreed += $ActualDirectoryFreed
Write-Log (
"Результат: {0}; освобождено: {1}; осталось: {2}; ошибок: {3}" -f `
$Category,
(Format-Size $ActualDirectoryFreed),
(Format-Size $SizeAfter),
$FailedCount
)
}
function Clear-OldCrashDumps {
param(
[string]$Path,
[int]$OlderThanDays
)
if (-not (Test-Path -LiteralPath $Path)) {
Write-Log (
"Отсутствует: {0}" -f $Path
)
return
}
$Limit = (Get-Date).AddDays(-$OlderThanDays)
$Files = Get-ChildItem `
-LiteralPath $Path `
-File `
-Force `
-ErrorAction SilentlyContinue |
Where-Object {
$_.LastWriteTime -lt $Limit
}
if (-not $Files) {
Write-Log (
"CrashDumps старше {0} дней не найдены: {1}" -f `
$OlderThanDays,
$Path
)
return
}
$SizeBefore = (
$Files |
Measure-Object `
-Property Length `
-Sum
).Sum
if (-not $SizeBefore) {
$SizeBefore = 0L
}
Write-Log (
"Очистка CrashDumps старше {0} дней: {1}; размер: {2}" -f `
$OlderThanDays,
$Path,
(Format-Size $SizeBefore)
)
$RemovedBytes = 0L
$FailedCount = 0
foreach ($File in $Files) {
try {
$Length = [long]$File.Length
Remove-Item `
-LiteralPath $File.FullName `
-Force `
-ErrorAction Stop
$RemovedBytes += $Length
}
catch {
$FailedCount++
Write-Log (
"Не удалось удалить дамп: {0}; ошибка: {1}" -f `
$File.FullName,
$_.Exception.Message
)
}
}
$Script:EstimatedFreed += $RemovedBytes
Write-Log (
"CrashDumps очищены: {0}; освобождено: {1}; ошибок: {2}" -f `
$Path,
(Format-Size $RemovedBytes),
$FailedCount
)
}
$IsAdmin = (
New-Object Security.Principal.WindowsPrincipal(
[Security.Principal.WindowsIdentity]::GetCurrent()
)
).IsInRole(
[Security.Principal.WindowsBuiltInRole]::Administrator
)
if (-not $IsAdmin) {
Write-Host ""
Write-Host "PowerShell необходимо запустить от имени администратора." `
-ForegroundColor Red
Write-Host ""
return
}
Write-Log "============================================================"
Write-Log "НАЧАЛО ОЧИСТКИ ПОЛЬЗОВАТЕЛЬСКИХ КЭШЕЙ"
Write-Log "============================================================"
$Before = Get-CDriveInfo
$Script:EstimatedFreed = 0L
Write-Log (
"До очистки: свободно {0} GB из {1} GB, {2}%" -f `
$Before.FreeGB,
$Before.SizeGB,
$Before.FreePct
)
Write-Log ""
Write-Log "Получение списка процессов и владельцев..."
$Script:OwnedProcesses = foreach (
$Process in Get-WmiObject -Class Win32_Process
) {
try {
$Owner = $Process.GetOwner()
if ($Owner.ReturnValue -eq 0) {
[pscustomobject]@{
User = $Owner.User
Domain = $Owner.Domain
Name = $Process.Name
ProcessId = $Process.ProcessId
}
}
}
catch {
}
}
Write-Log (
"Получено процессов: {0}" -f `
@($Script:OwnedProcesses).Count
)
$PythonRustProcesses = @(
"python.exe",
"pythonw.exe",
"pip.exe",
"pip3.exe",
"uv.exe",
"cargo.exe",
"rustc.exe",
"rustup.exe",
"rustup-init.exe",
"maturin.exe"
)
$JavaProcesses = @(
"java.exe",
"javaw.exe",
"soapui.exe",
"soapui-5.7.0.exe"
)
$RdpProcesses = @(
"mstsc.exe"
)
Write-Log ""
Write-Log "1. Очистка кэшей puccinialin"
Clear-CacheDirectory `
-User "A.Semenov" `
-Category "puccinialin" `
-Path "C:\Users\A.Semenov\AppData\Local\puccinialin" `
-BlockingProcesses $PythonRustProcesses
Clear-CacheDirectory `
-User "M.Rusakov" `
-Category "puccinialin" `
-Path "C:\Users\M.Rusakov\AppData\Local\puccinialin" `
-BlockingProcesses $PythonRustProcesses
Write-Log ""
Write-Log "2. Очистка pip cache"
Clear-CacheDirectory `
-User "A.Semenov" `
-Category "pip cache" `
-Path "C:\Users\A.Semenov\AppData\Local\pip\cache" `
-BlockingProcesses $PythonRustProcesses
Clear-CacheDirectory `
-User "M.Rusakov" `
-Category "pip cache" `
-Path "C:\Users\M.Rusakov\AppData\Local\pip\cache" `
-BlockingProcesses $PythonRustProcesses
Clear-CacheDirectory `
-User "S.Nikonov" `
-Category "pip cache" `
-Path "C:\Users\S.Nikonov\AppData\Local\pip\cache" `
-BlockingProcesses $PythonRustProcesses
Write-Log ""
Write-Log "3. Очистка старых пользовательских CrashDumps"
Clear-OldCrashDumps `
-Path "C:\Users\S.Nikonov\AppData\Local\CrashDumps" `
-OlderThanDays 7
Clear-OldCrashDumps `
-Path "C:\Users\t.volkova\AppData\Local\CrashDumps" `
-OlderThanDays 7
Clear-OldCrashDumps `
-Path "C:\Users\M.Rusakov\AppData\Local\CrashDumps" `
-OlderThanDays 7
Write-Log ""
Write-Log "4. Очистка кэша исходящих RDP-подключений"
Clear-CacheDirectory `
-User "S.Nikonov" `
-Category "RDP bitmap cache" `
-Path "C:\Users\S.Nikonov\AppData\Local\Microsoft\Terminal Server Client\Cache" `
-BlockingProcesses $RdpProcesses
Write-Log ""
Write-Log "5. Очистка OpenJFX cache"
Clear-CacheDirectory `
-User "S.Nikonov" `
-Category "OpenJFX cache" `
-Path "C:\Users\S.Nikonov\.openjfx\cache" `
-BlockingProcesses $JavaProcesses
Clear-CacheDirectory `
-User "M.Rusakov" `
-Category "OpenJFX cache" `
-Path "C:\Users\M.Rusakov\.openjfx\cache" `
-BlockingProcesses $JavaProcesses
$After = Get-CDriveInfo
$ActualFreed = [math]::Round(
$After.FreeGB - $Before.FreeGB,
2
)
Write-Log ""
Write-Log "============================================================"
Write-Log "ОЧИСТКА ЗАВЕРШЕНА"
Write-Log "============================================================"
Write-Log (
"До очистки свободно: {0} GB" -f `
$Before.FreeGB
)
Write-Log (
"После очистки свободно: {0} GB" -f `
$After.FreeGB
)
Write-Log (
"Освобождено по диску: {0} GB" -f `
$ActualFreed
)
Write-Log (
"Освобождено по удалённым файлам: {0}" -f `
(Format-Size $Script:EstimatedFreed)
)
Write-Log (
"Свободно сейчас: {0}%" -f `
$After.FreePct
)
Write-Log (
"Лог: {0}" -f $Log
)
Write-Host ""
Write-Host "============================================================"
Write-Host "СОСТОЯНИЕ ДИСКА C:"
Write-Host "============================================================"
Write-Host ""
Get-CDriveInfo |
Format-List
Write-Host "Лог: $Log" -ForegroundColor Cyan