Загрузка данных
$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 `
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 Get-PathSize {
param([string]$Path)
if (-not (Test-Path -LiteralPath $Path)) {
return 0L
}
$Item = Get-Item `
-LiteralPath $Path `
-Force `
-ErrorAction SilentlyContinue
if ($Item -and -not $Item.PSIsContainer) {
return [long]$Item.Length
}
$Sum = (
Get-ChildItem `
-LiteralPath $Path `
-File `
-Force `
-Recurse `
-ErrorAction SilentlyContinue |
Measure-Object `
-Property Length `
-Sum
).Sum
if ($Sum) {
return [long]$Sum
}
return 0L
}
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 Test-BlockingProcess {
param(
[string]$User,
[string[]]$ProcessNames
)
$Matches = $Script:OwnedProcesses |
Where-Object {
$_.User -ieq $User -and
$ProcessNames -icontains $_.Name
}
return @($Matches)
}
function Remove-CacheDirectory {
param(
[string]$User,
[string]$Category,
[string]$Path,
[string[]]$BlockingProcesses
)
if (-not (Test-Path -LiteralPath $Path)) {
Write-Log "Отсутствует: $Path"
return
}
$SizeBefore = Get-PathSize $Path
if ($SizeBefore -eq 0) {
Write-Log "Пустой каталог: $Path"
return
}
$Blockers = Test-BlockingProcess `
-User $User `
-ProcessNames $BlockingProcesses
if ($Blockers.Count -gt 0) {
$Names = (
$Blockers |
Select-Object -ExpandProperty Name -Unique
) -join ", "
Write-Log (
"ПРОПУЩЕНО: $Category — $Path; " +
"у пользователя $User работают процессы: $Names"
)
return
}
Write-Log (
"Очистка: $Category — $Path; размер: " +
(Format-Size $SizeBefore)
)
try {
Get-ChildItem `
-LiteralPath $Path `
-Force `
-ErrorAction SilentlyContinue |
ForEach-Object {
Remove-Item `
-LiteralPath $_.FullName `
-Recurse `
-Force `
-ErrorAction Stop
}
$SizeAfter = Get-PathSize $Path
$Freed = $SizeBefore - $SizeAfter
Write-Log (
"Успешно: освобождено " +
(Format-Size $Freed)
)
$Script:EstimatedFreed += $Freed
}
catch {
Write-Log (
"ОШИБКА очистки $Path: " +
$_.Exception.Message
)
}
}
function Remove-OldCrashDumps {
param(
[string]$User,
[string]$Path,
[int]$OlderThanDays
)
if (-not (Test-Path -LiteralPath $Path)) {
Write-Log "Отсутствует: $Path"
return
}
$Limit = (Get-Date).AddDays(-$OlderThanDays)
$Files = Get-ChildItem `
-LiteralPath $Path `
-File `
-Force `
-ErrorAction SilentlyContinue |
Where-Object {
$_.LastWriteTime -lt $Limit
}
$SizeBefore = (
$Files |
Measure-Object `
-Property Length `
-Sum
).Sum
if (-not $SizeBefore) {
Write-Log (
"Старые CrashDumps не найдены: $Path"
)
return
}
Write-Log (
"Очистка CrashDumps старше $OlderThanDays дней: " +
"$Path; размер: " +
(Format-Size $SizeBefore)
)
$RemovedBytes = 0L
foreach ($File in $Files) {
try {
$Length = [long]$File.Length
Remove-Item `
-LiteralPath $File.FullName `
-Force `
-ErrorAction Stop
$RemovedBytes += $Length
}
catch {
Write-Log (
"Не удалось удалить $($File.FullName): " +
$_.Exception.Message
)
}
}
Write-Log (
"CrashDumps: освобождено " +
(Format-Size $RemovedBytes)
)
$Script:EstimatedFreed += $RemovedBytes
}
$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
return
}
Write-Log "============================================================"
Write-Log "НАЧАЛО ОЧИСТКИ ПОЛЬЗОВАТЕЛЬСКИХ КЭШЕЙ"
Write-Log "============================================================"
$Before = Get-CDriveInfo
$Script:EstimatedFreed = 0L
Write-Log "До очистки свободно: $($Before.FreeGB) GB ($($Before.FreePct)%)"
Write-Log ""
Write-Log "Получение списка процессов и их владельцев..."
$Script:OwnedProcesses = foreach (
$Process in Get-WmiObject 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 "Процессы получены: $(@($Script:OwnedProcesses).Count)"
Write-Log ""
$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 "1. Очистка кэшей puccinialin"
Remove-CacheDirectory `
-User "A.Semenov" `
-Category "puccinialin" `
-Path "C:\Users\A.Semenov\AppData\Local\puccinialin" `
-BlockingProcesses $PythonRustProcesses
Remove-CacheDirectory `
-User "M.Rusakov" `
-Category "puccinialin" `
-Path "C:\Users\M.Rusakov\AppData\Local\puccinialin" `
-BlockingProcesses $PythonRustProcesses
Write-Log ""
Write-Log "2. Очистка pip cache"
Remove-CacheDirectory `
-User "A.Semenov" `
-Category "pip cache" `
-Path "C:\Users\A.Semenov\AppData\Local\pip\cache" `
-BlockingProcesses $PythonRustProcesses
Remove-CacheDirectory `
-User "M.Rusakov" `
-Category "pip cache" `
-Path "C:\Users\M.Rusakov\AppData\Local\pip\cache" `
-BlockingProcesses $PythonRustProcesses
Remove-CacheDirectory `
-User "S.Nikonov" `
-Category "pip cache" `
-Path "C:\Users\S.Nikonov\AppData\Local\pip\cache" `
-BlockingProcesses $PythonRustProcesses
Write-Log ""
Write-Log "3. Очистка старых пользовательских CrashDumps"
Remove-OldCrashDumps `
-User "S.Nikonov" `
-Path "C:\Users\S.Nikonov\AppData\Local\CrashDumps" `
-OlderThanDays 7
Remove-OldCrashDumps `
-User "t.volkova" `
-Path "C:\Users\t.volkova\AppData\Local\CrashDumps" `
-OlderThanDays 7
Remove-OldCrashDumps `
-User "M.Rusakov" `
-Path "C:\Users\M.Rusakov\AppData\Local\CrashDumps" `
-OlderThanDays 7
Write-Log ""
Write-Log "4. Очистка кэша исходящих RDP-подключений"
Remove-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"
Remove-CacheDirectory `
-User "S.Nikonov" `
-Category "OpenJFX cache" `
-Path "C:\Users\S.Nikonov\.openjfx\cache" `
-BlockingProcesses $JavaProcesses
Remove-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 "До очистки свободно: $($Before.FreeGB) GB"
Write-Log "После очистки свободно: $($After.FreeGB) GB"
Write-Log "Освобождено по диску: $ActualFreed GB"
Write-Log "По удалённым файлам: $(Format-Size $Script:EstimatedFreed)"
Write-Log "Свободно сейчас: $($After.FreePct)%"
Write-Log "Лог: $Log"
Write-Host ""
Write-Host "Состояние диска C:" -ForegroundColor Cyan
Get-CDriveInfo |
Format-List
Write-Host "Лог: $Log" -ForegroundColor Cyan