Skip to content

Commit e8bd342

Browse files
bivlkedclaude
andcommitted
fix: version display bugs and add operation timeouts (v2.11)
Fixed: - Version display bugs (banner and log showed v2.9 instead of current) - Outdated comment in Clear-WinCleanRecycleBin Added timeouts to prevent script hangs: - winget source update: 2 min - winget upgrade check: 5 min - winget upgrade all: 20 min - DISM /StartComponentCleanup: 15 min - Storage Sense: force stop on timeout Improved: - Docker detection: $LASTEXITCODE captured immediately - Browser cache statistics: null-coalescing for reliability - PowerShell path: removed hardcoded path - Code quality: comments for empty catch blocks Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent f2dfdfc commit e8bd342

5 files changed

Lines changed: 103 additions & 26 deletions

File tree

CHANGELOG.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,32 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
---
99

10+
## [2.11] - 2026-01-17
11+
12+
### Fixed
13+
- **Version display bugs**: Fixed hardcoded version strings that showed v2.9 instead of current version
14+
- Banner now uses dynamic `$script:Version` variable
15+
- Log file header now uses dynamic version
16+
- Removed outdated version comments from code
17+
18+
- **Outdated comment**: Updated comment in `Clear-WinCleanRecycleBin` that incorrectly stated name collision issue
19+
20+
### Added
21+
- **Operation timeouts to prevent script hangs**:
22+
- `winget upgrade --include-unknown` (check): 5-minute timeout
23+
- `winget upgrade --all` (install): 20-minute timeout
24+
- `winget source update`: 2-minute timeout (via background job)
25+
- `DISM /StartComponentCleanup`: 15-minute timeout
26+
- `Storage Sense`: Added force stop when timeout exceeded
27+
28+
### Improved
29+
- **Docker detection**: `$LASTEXITCODE` now captured immediately after command execution
30+
- **Browser cache statistics**: Added null-coalescing to prevent calculation errors
31+
- **PowerShell path**: Removed hardcoded path, now uses system PATH lookup
32+
- **Code quality**: Added explanatory comments to intentionally empty catch blocks
33+
34+
---
35+
1036
## [2.10] - 2026-01-17
1137

1238
### Added

CLAUDE.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# WinClean - Инструкции для Claude
22

33
> Последнее обновление: 2026-01-17
4-
> Текущая версия скрипта: 2.10
4+
> Текущая версия скрипта: 2.11
55
66
---
77

@@ -11,7 +11,7 @@
1111

1212
| Параметр | Значение |
1313
|----------|----------|
14-
| **Версия** | 2.10 |
14+
| **Версия** | 2.11 |
1515
| **Язык** | PowerShell 7.1+ |
1616
| **Платформа** | Windows 11 (23H2/24H2/25H2) |
1717
| **Лицензия** | MIT |
@@ -22,7 +22,7 @@
2222
### Статус публикации
2323

2424
- **GitHub**: ✅ Опубликован, активно развивается
25-
- **PSGallery**: ✅ Опубликован (v2.10, 17.01.2026)
25+
- **PSGallery**: ✅ Опубликован (v2.11, 17.01.2026)
2626
- **CI/CD**: ✅ GitHub Actions с PSScriptAnalyzer
2727

2828
---

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
### Ultimate Windows 11 Maintenance Script
88

9-
[![Version](https://img.shields.io/badge/version-2.10-blue.svg)](https://github.com/bivlked/WinClean/releases)
9+
[![Version](https://img.shields.io/badge/version-2.11-blue.svg)](https://github.com/bivlked/WinClean/releases)
1010
[![PSGallery](https://img.shields.io/powershellgallery/v/WinClean?label=PSGallery&logo=powershell&logoColor=white)](https://www.powershellgallery.com/packages/WinClean)
1111
[![CI](https://github.com/bivlked/WinClean/actions/workflows/ci.yml/badge.svg)](https://github.com/bivlked/WinClean/actions/workflows/ci.yml)
1212
[![PowerShell 7.1+](https://img.shields.io/badge/PowerShell-7.1%2B-5391FE?logo=powershell&logoColor=white)](https://github.com/PowerShell/PowerShell)
@@ -319,7 +319,7 @@ C:\Users\YourName\
319319

320320
```
321321
┌────────────────────────────────────────────────────────────────┐
322-
│ WinClean v2.10
322+
│ WinClean v2.11
323323
├────────────────────────────────────────────────────────────────┤
324324
│ PREPARATION │
325325
│ ├─ ✓ Check Administrator Rights │

README_RU.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
### Комплексный скрипт обслуживания Windows 11
88

9-
[![Версия](https://img.shields.io/badge/версия-2.10-blue.svg)](https://github.com/bivlked/WinClean/releases)
9+
[![Версия](https://img.shields.io/badge/версия-2.11-blue.svg)](https://github.com/bivlked/WinClean/releases)
1010
[![PSGallery](https://img.shields.io/powershellgallery/v/WinClean?label=PSGallery&logo=powershell&logoColor=white)](https://www.powershellgallery.com/packages/WinClean)
1111
[![CI](https://github.com/bivlked/WinClean/actions/workflows/ci.yml/badge.svg)](https://github.com/bivlked/WinClean/actions/workflows/ci.yml)
1212
[![PowerShell 7.1+](https://img.shields.io/badge/PowerShell-7.1%2B-5391FE?logo=powershell&logoColor=white)](https://github.com/PowerShell/PowerShell)
@@ -319,7 +319,7 @@ C:\Users\ВашеИмя\
319319

320320
```
321321
┌────────────────────────────────────────────────────────────────┐
322-
│ WinClean v2.10
322+
│ WinClean v2.11
323323
├────────────────────────────────────────────────────────────────┤
324324
│ ПОДГОТОВКА │
325325
│ ├─ ✓ Проверка прав администратора │

WinClean.ps1

Lines changed: 70 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<#PSScriptInfo
2-
.VERSION 2.10
2+
.VERSION 2.11
33
.GUID 8f7c3b2a-1d4e-5f6a-9b8c-0d1e2f3a4b5c
44
.AUTHOR bivlked
55
.COMPANYNAME
@@ -12,16 +12,16 @@
1212
.REQUIREDSCRIPTS
1313
.EXTERNALSCRIPTDEPENDENCIES
1414
.RELEASENOTES
15+
v2.11: Added timeouts for winget/DISM operations, fixed version display, improved reliability
1516
v2.10: Added auto-update check at startup (checks PSGallery for new version)
1617
v2.9: Fixed PSWindowsUpdate installation hanging (TLS 1.2, timeouts)
1718
v2.8: Fixed Disk Cleanup timeout issues
18-
v2.7: UI improvements for final statistics
1919
.PRIVATEDATA
2020
#>
2121

2222
<#
2323
.SYNOPSIS
24-
WinClean - Ultimate Windows 11 Maintenance Script v2.10
24+
WinClean - Ultimate Windows 11 Maintenance Script v2.11
2525
.DESCRIPTION
2626
Комплексный скрипт для обновления и очистки Windows 11:
2727
- Обновление Windows (включая драйверы)
@@ -35,8 +35,13 @@
3535
- Подробный цветной вывод + лог-файл
3636
.NOTES
3737
Author: biv
38-
Version: 2.10
38+
Version: 2.11
3939
Requires: PowerShell 7.1+, Windows 11, Administrator rights
40+
Changes in 2.11:
41+
- Fixed version display bugs (banner and log showed v2.9 instead of current version)
42+
- Added timeouts for winget/DISM operations to prevent script hangs
43+
- Added force stop for Storage Sense when timeout exceeded
44+
- Improved Docker detection and browser cache statistics reliability
4045
Changes in 2.10:
4146
- Added auto-update check: script checks PSGallery for newer version at startup
4247
- Added Test-ScriptUpdate function: compares local version with PSGallery
@@ -205,7 +210,7 @@ if (-not $LogPath) {
205210
}
206211

207212
# Script version (single source of truth for version checking)
208-
$script:Version = "2.10"
213+
$script:Version = "2.11"
209214

210215
# Protected paths that should never be deleted
211216
$script:ProtectedPaths = @(
@@ -942,7 +947,8 @@ function New-SystemRestorePoint {
942947
}
943948
"@
944949

945-
$result = & "$env:SystemRoot\System32\WindowsPowerShell\v1.0\powershell.exe" `
950+
# Use Windows PowerShell 5.1 (Checkpoint-Computer not available in PS7)
951+
$result = & powershell.exe `
946952
-NoProfile -NoLogo -ExecutionPolicy Bypass -Command $scriptBlock 2>&1
947953

948954
if ($result -like "SUCCESS*") {
@@ -1014,7 +1020,7 @@ function Update-WindowsSystem {
10141020
# Clear any lingering progress bar before module installation
10151021
Write-Progress -Activity "Windows Update" -Completed -ErrorAction SilentlyContinue
10161022

1017-
# Check PowerShell Gallery availability first (v2.9)
1023+
# Check PowerShell Gallery availability first
10181024
Write-Log "Checking PowerShell Gallery availability..." -Level INFO
10191025
if (-not (Test-PSGalleryConnection)) {
10201026
Write-Log "PowerShell Gallery is unavailable" -Level ERROR
@@ -1026,7 +1032,7 @@ function Update-WindowsSystem {
10261032

10271033
Write-Log "Installing PSWindowsUpdate module..." -Level INFO
10281034

1029-
# Ensure NuGet provider with timeout (v2.9)
1035+
# Ensure NuGet provider with timeout
10301036
$nuget = Get-PackageProvider -Name NuGet -ErrorAction SilentlyContinue
10311037
if (-not $nuget -or $nuget.Version -lt [version]"2.8.5.201") {
10321038
Write-Log "Installing NuGet provider..." -Level INFO
@@ -1039,7 +1045,7 @@ function Update-WindowsSystem {
10391045
Write-Log "NuGet provider installed" -Level SUCCESS
10401046
}
10411047

1042-
# Install PSWindowsUpdate module with timeout (v2.9)
1048+
# Install PSWindowsUpdate module with timeout
10431049
if (-not (Install-ModuleWithTimeout -ModuleName "PSWindowsUpdate" -TimeoutSeconds 120)) {
10441050
Write-Log "Failed to install PSWindowsUpdate - Windows Update skipped" -Level ERROR
10451051
Write-Log "Try manual installation: Install-Module PSWindowsUpdate -Force -Scope CurrentUser" -Level INFO
@@ -1188,7 +1194,14 @@ function Update-Applications {
11881194
# Update sources only if not in ReportOnly mode (source update modifies state)
11891195
if (-not $ReportOnly) {
11901196
Write-Log "Updating winget sources..." -Level INFO
1191-
& $wingetPath source update 2>&1 | Out-Null
1197+
# Run with timeout to prevent hanging
1198+
$job = Start-Job -ScriptBlock { param($path) & $path source update 2>&1 } -ArgumentList $wingetPath
1199+
$completed = $job | Wait-Job -Timeout 120 # 2 minutes timeout
1200+
if (-not $completed) {
1201+
$job | Stop-Job
1202+
Write-Log "Winget source update timed out" -Level WARNING
1203+
}
1204+
$job | Remove-Job -Force -ErrorAction SilentlyContinue
11921205
}
11931206

11941207
# Get available updates (use --include-unknown to match actual upgrade behavior)
@@ -1197,7 +1210,17 @@ function Update-Applications {
11971210
$tempFile = [System.IO.Path]::GetTempFileName()
11981211
$tempErrorFile = [System.IO.Path]::GetTempFileName()
11991212
$process = Start-Process -FilePath $wingetPath -ArgumentList "upgrade", "--include-unknown" `
1200-
-NoNewWindow -RedirectStandardOutput $tempFile -RedirectStandardError $tempErrorFile -PassThru -Wait
1213+
-NoNewWindow -RedirectStandardOutput $tempFile -RedirectStandardError $tempErrorFile -PassThru
1214+
1215+
# Wait with timeout (5 minutes for check operation)
1216+
$timeoutMs = 300000
1217+
if (-not $process.WaitForExit($timeoutMs)) {
1218+
$process.Kill()
1219+
Write-Log "Winget upgrade check timed out after 5 minutes" -Level WARNING
1220+
$script:Stats.WarningsCount++
1221+
Remove-Item $tempFile, $tempErrorFile -Force -ErrorAction SilentlyContinue
1222+
return
1223+
}
12011224

12021225
$output = Get-Content $tempFile -Raw -Encoding UTF8 -ErrorAction SilentlyContinue
12031226
$errorOutput = Get-Content $tempErrorFile -Raw -Encoding UTF8 -ErrorAction SilentlyContinue
@@ -1267,7 +1290,16 @@ function Update-Applications {
12671290
)
12681291

12691292
$upgradeProcess = Start-Process -FilePath $wingetPath -ArgumentList $upgradeArgs `
1270-
-NoNewWindow -PassThru -Wait
1293+
-NoNewWindow -PassThru
1294+
1295+
# Wait with timeout (20 minutes for upgrade operation - can take long with many updates)
1296+
$timeoutMs = 1200000
1297+
if (-not $upgradeProcess.WaitForExit($timeoutMs)) {
1298+
$upgradeProcess.Kill()
1299+
Write-Log "Winget upgrade timed out after 20 minutes" -Level WARNING
1300+
$script:Stats.WarningsCount++
1301+
return
1302+
}
12711303

12721304
$script:Stats.AppUpdatesCount = $updateCount
12731305

@@ -1408,6 +1440,7 @@ function Clear-BrowserCaches {
14081440

14091441
# Measure size after cleanup to get actual freed space
14101442
$sizeAfter = ($allPaths | ForEach-Object { Get-FolderSize -Path $_.Path } | Measure-Object -Sum).Sum
1443+
$sizeAfter = [long]($sizeAfter ?? 0) # Ensure non-null value
14111444
$freedSpace = $sizeBefore - $sizeAfter
14121445

14131446
# Update statistics with actual freed space (not estimated)
@@ -1476,7 +1509,7 @@ function Clear-WinCleanRecycleBin {
14761509
}
14771510

14781511
try {
1479-
# Use full cmdlet path to avoid recursion (our function has same name as cmdlet)
1512+
# Use full cmdlet path to explicitly call the built-in cmdlet
14801513
Microsoft.PowerShell.Management\Clear-RecycleBin -Force -ErrorAction Stop
14811514
Write-Log "Recycle Bin emptied" -Level SUCCESS
14821515
} catch {
@@ -2028,8 +2061,11 @@ function Clear-DockerWSL {
20282061
$dockerRunning = $false
20292062
try {
20302063
$dockerInfo = docker info 2>&1
2031-
$dockerRunning = $LASTEXITCODE -eq 0
2032-
} catch { }
2064+
$exitCode = $LASTEXITCODE # Capture immediately after command
2065+
$dockerRunning = $exitCode -eq 0
2066+
} catch {
2067+
# Docker command failed to execute (not installed or path issue)
2068+
}
20332069

20342070
if ($dockerRunning) {
20352071
if ($ReportOnly) {
@@ -2250,7 +2286,16 @@ function Invoke-DISMCleanup {
22502286
try {
22512287
$dismProcess = Start-Process -FilePath "$env:SystemRoot\System32\Dism.exe" `
22522288
-ArgumentList "/Online", "/Cleanup-Image", "/StartComponentCleanup", "/ResetBase" `
2253-
-NoNewWindow -PassThru -Wait
2289+
-NoNewWindow -PassThru
2290+
2291+
# Wait with timeout (15 minutes for DISM operation)
2292+
$timeoutMs = 900000
2293+
if (-not $dismProcess.WaitForExit($timeoutMs)) {
2294+
$dismProcess.Kill()
2295+
Write-Log "DISM cleanup timed out after 15 minutes" -Level WARNING
2296+
$script:Stats.WarningsCount++
2297+
return
2298+
}
22542299

22552300
switch ($dismProcess.ExitCode) {
22562301
0 { Write-Log "DISM cleanup completed successfully" -Level SUCCESS }
@@ -2321,7 +2366,13 @@ function Invoke-StorageSense {
23212366
}
23222367

23232368
if ($elapsed -ge $timeout) {
2324-
Write-Log "Storage Sense timed out after $timeout seconds (may still be running)" -Level WARNING
2369+
Write-Log "Storage Sense timed out after $timeout seconds" -Level WARNING
2370+
# Force stop the task if still running
2371+
$task = Get-ScheduledTask -TaskPath $ssTaskPath -TaskName $ssTaskName -ErrorAction SilentlyContinue
2372+
if ($task -and $task.State -eq 'Running') {
2373+
Stop-ScheduledTask -TaskPath $ssTaskPath -TaskName $ssTaskName -ErrorAction SilentlyContinue
2374+
Write-Log "Storage Sense task stopped" -Level INFO
2375+
}
23252376
$script:Stats.WarningsCount++
23262377
}
23272378
} else {
@@ -2398,7 +2449,7 @@ function Show-Banner {
23982449
║ ╚██████╗███████╗███████╗██║ ██║██║ ╚████║ ║
23992450
║ ╚═════╝╚══════╝╚══════╝╚═╝ ╚═╝╚═╝ ╚═══╝ ║
24002451
║ ║
2401-
║ Ultimate Windows 11 Maintenance Script v2.9
2452+
║ Ultimate Windows 11 Maintenance Script v$($script:Version)
24022453
║ ║
24032454
╚══════════════════════════════════════════════════════════════════════╝
24042455
@@ -2573,7 +2624,7 @@ function Show-FinalStatistics {
25732624

25742625
function Start-WinClean {
25752626
# Initialize log
2576-
"WinClean v2.9 - Started at $(Get-Date)" | Out-File -FilePath $script:LogPath -Encoding utf8
2627+
"WinClean v$($script:Version) - Started at $(Get-Date)" | Out-File -FilePath $script:LogPath -Encoding utf8
25772628
"=" * 70 | Out-File -FilePath $script:LogPath -Append -Encoding utf8
25782629

25792630
# Enable TLS 1.2 for all HTTPS connections (required by PowerShell Gallery, NuGet, etc.)

0 commit comments

Comments
 (0)