Skip to content

fix: address 6 medium bugs (#311)#351

Merged
laurentiu021 merged 1 commit into
mainfrom
fix/medium-bugs-311
May 14, 2026
Merged

fix: address 6 medium bugs (#311)#351
laurentiu021 merged 1 commit into
mainfrom
fix/medium-bugs-311

Conversation

@laurentiu021

@laurentiu021 laurentiu021 commented May 14, 2026

Copy link
Copy Markdown
Owner

Summary

Fixes 6 medium-priority bugs identified in the code review.

Changes

  1. DuplicateFileGroup — added [NotifyPropertyChangedFor(nameof(WastedBytes))] on _count and _fileSize so UI updates when these change.
  2. UpdateService — Map() now returns null for pre-release and draft releases, filtering them from GetRecentAsync results.
  3. ServiceManagerService — StartService checks for StartPending state before calling Start(), preventing InvalidOperationException.
  4. DiskAnalyzerService — MeasureFolder now tracks actual UnauthorizedAccessException occurrences instead of using the heuristic (size==0 && files==0 && folders==0) which incorrectly flagged empty directories.
  5. WindowsUpdateViewModel — null-conditional on Application.Current?.Shutdown() prevents NRE in test/non-standard hosting scenarios.
  6. TuneUpService — SHEmptyRecycleBin HRESULT is now checked; S_OK or 0x80070012 (bin empty) = success, anything else = false.

Tests

  • New: DuplicateFileGroupTests (8 tests) — WastedBytes calculation, PropertyChanged notifications
  • New: DiskAnalyzerServiceTests.Analyze_EmptySubfolder_NotMarkedAsAccessDenied

Closes #311

Summary by CodeRabbit

  • Bug Fixes

    • Fixed duplicate file calculations to properly update when file count or size changes
    • Corrected empty directory detection to accurately report folder access issues
    • Prevented errors when starting services already in progress
    • Improved recycle bin emptying to properly report failures
    • Filtered out pre-release and draft updates from version checks
    • Enhanced application stability during shutdown
  • Tests

    • Added test coverage for duplicate file detection and disk analysis functionality

Review Change Stack

…ceManager, DiskAnalyzer, WindowsUpdateVM, TuneUpService (#311)
@coderabbitai

coderabbitai Bot commented May 14, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

This PR resolves six targeted bugs across models and services: WastedBytes property notifications in DuplicateFileGroup, accurate access-denied detection in disk analysis, service restart state checking, recycle bin operation error validation, GitHub prerelease filtering, and null-safe application shutdown.

Changes

Multiple Bug Fixes: Models, Services, and Utilities

Layer / File(s) Summary
DuplicateFileGroup WastedBytes notifications
SysManager/SysManager/Models/DuplicateFileGroup.cs, SysManager/SysManager.Tests/DuplicateFileGroupTests.cs
DuplicateFileGroup._fileSize and _count ObservableProperties now include NotifyPropertyChangedFor(nameof(WastedBytes)) so UI updates when either backing field changes. Test suite validates WastedBytes calculation for counts 3, 1, and 0; verifies PropertyChanged notifications for FileSize, Count, and Hash changes; and confirms DuplicateFileEntry properties raise PropertyChanged events.
DiskAnalyzerService access-denied flag accuracy
SysManager/SysManager/Services/DiskAnalyzerService.cs, SysManager/SysManager.Tests/DiskAnalyzerServiceTests.cs
MeasureFolder now explicitly propagates an accessDenied boolean through its return tuple, setting the flag true whenever UnauthorizedAccessException occurs during file/directory enumeration, subdirectory traversal, or attribute checks. DiskUsageEntry.IsAccessDenied is assigned directly from this propagated flag instead of being inferred from zero sizes, preventing empty directories from being incorrectly marked as access denied.
Service state and system integration fixes
SysManager/SysManager/Services/ServiceManagerService.cs, SysManager/SysManager/Services/TuneUpService.cs, SysManager/SysManager/Services/UpdateService.cs, SysManager/SysManager/ViewModels/WindowsUpdateViewModel.cs
ServiceManagerService.StartService now checks for Running or StartPending states before calling Start(). TuneUpService.EmptyRecycleBin checks the HRESULT return value and succeeds only on success or ERROR_NO_MORE_FILES. UpdateService.Map filters GitHub releases by returning null for prerelease or draft releases. WindowsUpdateViewModel.RelaunchAsAdmin uses null-conditional Application.Current?.Shutdown().
Release documentation
CHANGELOG.md
Version 0.48.3 (2026-05-14) release notes document all six bug fixes.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • laurentiu021/SystemManager#294: Both PRs modify DuplicateFileGroup.WastedBytes handling—main PR adds property-change notifications when dependencies change, while the related PR adjusts the WastedBytes formula itself.

Poem

🐰 Six little bugs that scattered far and wide,
Now caught and fixed with careful, watchful pride!
From waste bytes humming to access paths clear,
The services hum in harmony here.
A shutdown so gentle, a recycle bin true—
Release notes dancing in 0.48.3 for you! 🎉

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 21.05% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the pull request's primary change: addressing six medium-priority bugs with a reference to the issue number (#311).
Linked Issues check ✅ Passed All six coding requirements from issue #311 are met: WastedBytes notifications [BUG-002], pre-release filtering [BUG-004], StartPending check [BUG-005], access-denied detection fix [BUG-006], null-conditional for Application.Current [BUG-007], and HRESULT validation [BUG-003].
Out of Scope Changes check ✅ Passed All changes are scoped to the six bugs identified in issue #311; no unrelated or out-of-scope modifications are present.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/medium-bugs-311

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov-commenter

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

❌ Patch coverage is 19.04762% with 17 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
...nager/SysManager/Services/ServiceManagerService.cs 0.00% 9 Missing ⚠️
...Manager/SysManager/Services/DiskAnalyzerService.cs 50.00% 4 Missing ⚠️
SysManager/SysManager/Services/TuneUpService.cs 0.00% 2 Missing ⚠️
SysManager/SysManager/Services/UpdateService.cs 0.00% 0 Missing and 1 partial ⚠️
...er/SysManager/ViewModels/WindowsUpdateViewModel.cs 0.00% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@SysManager/SysManager/ViewModels/WindowsUpdateViewModel.cs`:
- Line 77: Several shutdown calls directly invoke
System.Windows.Application.Current.Shutdown(), which can throw
NullReferenceException in tests or non-standard hosts; update every occurrence
to use the null-conditional operator
(System.Windows.Application.Current?.Shutdown())—specifically replace the direct
calls in WindowsUpdateViewModel's relaunch/shutdown paths, the shutdown call in
DashboardViewModel, the call in AppUpdatesViewModel, and the call in
TrayIconService so each uses ?.Shutdown() to safely no-op when Current is null.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: b36b11c7-99f8-49c4-9684-5255dc1aa92f

📥 Commits

Reviewing files that changed from the base of the PR and between 9efbe70 and 0647f24.

📒 Files selected for processing (9)
  • CHANGELOG.md
  • SysManager/SysManager.Tests/DiskAnalyzerServiceTests.cs
  • SysManager/SysManager.Tests/DuplicateFileGroupTests.cs
  • SysManager/SysManager/Models/DuplicateFileGroup.cs
  • SysManager/SysManager/Services/DiskAnalyzerService.cs
  • SysManager/SysManager/Services/ServiceManagerService.cs
  • SysManager/SysManager/Services/TuneUpService.cs
  • SysManager/SysManager/Services/UpdateService.cs
  • SysManager/SysManager/ViewModels/WindowsUpdateViewModel.cs
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Build & unit tests
  • GitHub Check: Analyze (csharp)
🔇 Additional comments (10)
SysManager/SysManager/Services/UpdateService.cs (1)

263-263: LGTM!

SysManager/SysManager/Services/TuneUpService.cs (1)

221-223: LGTM!

SysManager/SysManager/Models/DuplicateFileGroup.cs (1)

17-23: LGTM!

SysManager/SysManager/Services/DiskAnalyzerService.cs (1)

85-86: LGTM!

Also applies to: 96-97, 127-127, 132-132, 144-145, 147-148, 158-159, 171-172, 179-179

SysManager/SysManager/Services/ServiceManagerService.cs (1)

89-102: LGTM!

CHANGELOG.md (1)

9-25: LGTM!

SysManager/SysManager.Tests/DiskAnalyzerServiceTests.cs (1)

130-141: LGTM!

SysManager/SysManager.Tests/DuplicateFileGroupTests.cs (3)

15-41: LGTM!


43-87: LGTM!


91-109: LGTM!

{
if (AdminHelper.RelaunchAsAdmin())
System.Windows.Application.Current.Shutdown();
System.Windows.Application.Current?.Shutdown();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify whether any non-null-safe shutdown calls still exist.
# Expected: no matches for direct Application.Current.Shutdown(...)

rg -nP --type=cs 'Application\.Current\.Shutdown\s*\('
rg -nP --type=cs 'Application\.Current\?\.\s*Shutdown\s*\('

Repository: laurentiu021/SystemManager

Length of output: 1498


Apply null-guards to all relaunch shutdown paths.

Line 77 was fixed, but lines 114 and 350 in WindowsUpdateViewModel.cs still call System.Windows.Application.Current.Shutdown() directly. Additionally, the same null-reference vulnerability exists at:

  • DashboardViewModel.cs:126
  • AppUpdatesViewModel.cs:39
  • TrayIconService.cs:118

Apply the null-coalescing operator (?.) to all of these calls to prevent null-reference exceptions in tests or non-standard hosting scenarios.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@SysManager/SysManager/ViewModels/WindowsUpdateViewModel.cs` at line 77,
Several shutdown calls directly invoke
System.Windows.Application.Current.Shutdown(), which can throw
NullReferenceException in tests or non-standard hosts; update every occurrence
to use the null-conditional operator
(System.Windows.Application.Current?.Shutdown())—specifically replace the direct
calls in WindowsUpdateViewModel's relaunch/shutdown paths, the shutdown call in
DashboardViewModel, the call in AppUpdatesViewModel, and the call in
TrayIconService so each uses ?.Shutdown() to safely no-op when Current is null.

Comment thread SysManager/SysManager/Services/TuneUpService.cs Dismissed
@laurentiu021
laurentiu021 merged commit d7e837f into main May 14, 2026
5 checks passed
@laurentiu021
laurentiu021 deleted the fix/medium-bugs-311 branch May 14, 2026 08:24
laurentiu021 added a commit that referenced this pull request May 22, 2026
…event handler leaks (#351)

## Summary

Fix memory leaks that cause the application to become unresponsive or
crash during extended use.

## Root cause

Three categories of resource leaks were identified through static
analysis:

### 1. CancellationTokenSource leak (8 ViewModels, 15 locations)
Every time a user triggered a refresh/scan/list operation, a new
`CancellationTokenSource` was created without disposing the previous
one. Each undisposed CTS holds an internal `WaitHandle`. Over extended
use (dozens of refreshes), these accumulate and contribute to memory
exhaustion.

**Affected ViewModels:** WindowsUpdateViewModel (5),
UninstallerViewModel (2), SystemHealthViewModel (2), AppUpdatesViewModel
(2), DriversViewModel (1), LogsViewModel (1), DuplicateFileViewModel
(1), DiskAnalyzerViewModel (1).

**Fix:** Add `_cts?.Dispose()` before every `_cts = new
CancellationTokenSource()`.

### 2. Process object leak in App.ActivateExistingInstance
`Process.GetProcessesByName()` returns Process objects that must be
disposed. Neither the enumerated processes nor the current process were
being disposed.

**Fix:** `using var current` + `try/finally { proc.Dispose(); }` in the
loop.

### 3. PropertyChanged event handler leak in Network tab
`AddTarget()` subscribed an anonymous lambda to
`target.PropertyChanged`. When targets were removed via
`RemoveTargetInternal()`, the handler was never unsubscribed — the
lambda captured the outer scope, preventing GC from collecting removed
targets.

**Fix:** Store handlers in a `Dictionary<string,
PropertyChangedEventHandler>` keyed by host. Unsubscribe in
`RemoveTargetInternal()` before removing the target.

## Files changed (11)
- `App.xaml.cs` — Process disposal
- `NetworkSharedState.cs` — event handler tracking + unsubscribe
- `NetworkViewModel.cs` — event handler tracking + unsubscribe
- `WindowsUpdateViewModel.cs` — CTS disposal (5 locations)
- `UninstallerViewModel.cs` — CTS disposal (2)
- `SystemHealthViewModel.cs` — CTS disposal (2)
- `AppUpdatesViewModel.cs` — CTS disposal (2)
- `DriversViewModel.cs` — CTS disposal (1)
- `LogsViewModel.cs` — CTS disposal (1)
- `DuplicateFileViewModel.cs` — CTS disposal (1)
- `DiskAnalyzerViewModel.cs` — CTS disposal (1)

## Testing
- Build: 0 errors (both main project and test project)
- All changes are additive Dispose/unsubscribe calls — no behavioral
change
- Existing tests unaffected

Closes #161

Co-authored-by: laurentiu021 <laurentiu021@users.noreply.github.com>
laurentiu021 added a commit that referenced this pull request May 22, 2026
…Model (#358)

## Summary

Add `_cts?.Dispose()` before each `new CancellationTokenSource()` for
all four CTS fields in CleanupViewModel (`_tempCts`, `_binCts`,
`_sfcCts`, `_dismCts`).

## Problem

Found during closed-bug regression audit: the CTS disposal pattern from
PR #351 (fix #161 memory leaks) was correctly applied in 8 other
ViewModels but missed in CleanupViewModel. Repeated Clean TEMP / Empty
Recycle Bin / SFC / DISM operations leak CancellationTokenSource
handles.

## Fix

Same one-line pattern already used everywhere else:
```csharp
_cts?.Dispose();
_cts = new CancellationTokenSource();
```

Applied to all 4 CTS fields in CleanupViewModel.

## Files changed

- `SysManager/ViewModels/CleanupViewModel.cs` — 4 lines added

Co-authored-by: laurentiu021 <laurentiu021@users.noreply.github.com>
laurentiu021 added a commit that referenced this pull request May 22, 2026
…ceManager, DiskAnalyzer, WindowsUpdateVM, TuneUpService (#311) (#351)

Co-authored-by: laurentiu021 <laurentiu021@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Multiple medium bugs — DuplicateFileGroup, UpdateService, ServiceManager, DiskAnalyzer, WindowsUpdateVM

3 participants